1
0
mirror of https://github.com/gryf/tagbar.git synced 2025-12-17 11:30:28 +01:00

Move tests into separate repository

This commit is contained in:
Jan Larres
2013-04-24 15:57:22 +12:00
parent e6e084e8b0
commit f0f9d66465
128 changed files with 0 additions and 54624 deletions

1
.gitattributes vendored
View File

@@ -2,4 +2,3 @@
.gitattributes export-ignore
README export-ignore
.info export-ignore
tests/** export-ignore

File diff suppressed because it is too large Load Diff

View File

@@ -1,38 +0,0 @@
<project name="MyProject" default="dist" basedir=".">
<description>
simple example build file
</description>
<!-- set global properties for this build -->
<property name="src" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<target name="init">
<!-- Create the time stamp -->
<tstamp/>
<!-- Create the build directory structure used by compile -->
<mkdir dir="${build}"/>
</target>
<target name="compile" depends="init"
description="compile the source " >
<!-- Compile the java code from ${src} into ${build} -->
<javac srcdir="${src}" destdir="${build}"/>
</target>
<target name="dist" depends="compile"
description="generate the distribution" >
<!-- Create the distribution directory -->
<mkdir dir="${dist}/lib"/>
<!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file -->
<jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/>
</target>
<target name="clean"
description="clean up" >
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="${build}"/>
<delete dir="${dist}"/>
</target>
</project>

View File

@@ -1,39 +0,0 @@
Game Port
; GAMEPORT.ASM
;
.MODEL TINY
.DATA
yes DB 13,10,"Game port is installed.",13,10,"$"
no DB 13,10,"Game port is not installed.",13,10,"$"
.CODE
ORG 100h
start: mov al, 1 ;value to write to port
mov dx, 201h ;port number
out dx, al ;write to port
mov cx, 0F00h ;# of loops
port_loop:
in al, dx ;read from port
and al, 0Fh ;if jstick present, then AL should be
cmp al, 0Fh ; 0Fh after ANDing with 0Fh.
je jstick_exists
loop port_loop
mov dx, OFFSET no ;gameport not installed
jmp SHORT done
jstick_exists:
mov dx, OFFSET yes ;gameport installed
done: mov ah, 9h
int 21h
mov ax, 4c00h
int 21h
END start

View File

@@ -1,164 +0,0 @@
Gets a list of Queue servers under Novell Netware 3.11
%PAGESIZE 55,200
%SUBTTL "Get List of Queue Servers under Netware 3.11"
; Net_Q.Asm
;
.MODEL SMALL
.STACK 100h
DOSint macro function
mov ah,function
int 21h
ENDM
.DATA
STDOUT = 1 ; the stdout device handle
DOS_WRITE_TO_HANDLE = 040h ; Write to File Handle
DOS_TERMINATE_EXE = 04Ch ; Terminate Program
NOVELL_FUNCTION = 0E3h
;
; Object Types
; note that they're all big endian
;
OT_USER = 0100h
OT_USER_GROUP = 0200h
OT_PRINT_QUEUE = 0300h ; Print Queue object type
OT_FILE_SERVER = 0400h
BragMsg DB 0dh,0ah,"NET_Q.EXE",9,"WWW"
DB 9,"Version 1.00",0dh,0ah
DB 9,9,"released to the public domain by the author",0dh,0ah,0dh,0ah
BragLen = $ - BragMsg
Crlf DB 0dh,0ah,0
SCAN_REQ STRUC ; bindery ScanObject request packet structure
MyLength DW 55 ; the length of this buffer
Function DB 37h ; scan object subfunction number
ObjectID DD -1 ; all ones for initial object search
ObjectType DW -1 ; wild card -- looks for all objects
ObjNameLen DB 1 ; at least one character
ObjName DB 47 DUP ('*') ; fill with wildcards to start
SCAN_REQ ENDS
SCAN_REP STRUC ; bindery ScanObject request packet structure
MyLength DW 57
RObjectID DD 0 ; all ones for initial object search
RObjectType DW 0 ; wild card -- looks for all objects
RObjName DB 48 DUP (0) ; fill with wildcards to start
ObjFlag DB 0
ObjSecurty DB 0
ObjHasProp DB 0
ENDS
ScanObjReq SCAN_REQ <>
ScanObjRep SCAN_REP <>
.CODE
;
; This is the main part of the code
;
; Test code gets and prints the name of all print queues from the
; logged server -- NO ERROR CHECKING IS DONE, so be careful!
;
Start:
mov ax,@data
mov ds,ax ; set up the data segment
mov dx,OFFSET BragMsg ; prepare to print out brag line(s)
mov cx,BragLen
mov bx,STDOUT ; print to STDOUT
DOSint DOS_WRITE_TO_HANDLE
jc Exit ; if carry is set, there was an error
mov [ScanObjReq.ObjectType],OT_PRINT_QUEUE
;
; in this case the name is already set up, (a wildcard) but if a
; specific name were desired, it would be moved to
; ScanObjReq.ObjName, with the appropriate length (not including
; optional terminating NULL char set up in ScanObjReq.ObjNameLen.
;
@@MoreQueues:
call BindScan
jc Exit
lea dx,[ScanObjRep.ObjName]
call Puts
lea dx,[Crlf]
call Puts
jmp @@MoreQueues
Exit:
DOSint DOS_TERMINATE_EXE ; return with error code preset in AL
;
; BindScan
;
; scans the bindery for the object name set in the request buffer
;
BindScan proc
push ds si di es dx ax
lea si,[ScanObjReq] ; point DS:DI to request buffer
mov dx,ds
mov es,dx
lea di,[ScanObjRep] ; point ES:SI to reply buffer
DOSint NOVELL_FUNCTION
jb @@Exit
cld ; make sure to count up
mov si,OFFSET ScanObjRep.ObjectID
mov di,OFFSET ScanObjReq.ObjectID
movsw
movsw
clc
@@Exit:
pop ax dx es di si ds
ret
BindScan endp
; Puts
;
; prints a NUL terminated string to stdout
;
; INPUTS: ds:dx points to ASCIIZ string
;
; OUTPUTS: prints string to stdout
;
; RETURNS: ax = number of bytes actually printed
; carry set on error
;
; DESTROYED: ax
;
Puts proc
push bx cx di es
push ds
pop es
mov cx,0ffffh ; maximum length of string
mov di,dx
cld
mov al,0 ; we're looking for NUL
repne scasb
dec di
mov cx,di
sub cx,dx
mov bx,STDOUT ; write to this device
DOSint DOS_WRITE_TO_HANDLE
pop es di cx bx
ret
Puts endp
END Start

View File

@@ -1,14 +0,0 @@
<html>
<body>
<%
dim fs,d
set fs=Server.CreateObject("Scripting.FileSystemObject")
set d=fs.GetDrive("c:")
Response.Write("The serialnumber is " & d.SerialNumber)
set d=nothing
set fs=nothing
%>
</body>
</html>

View File

@@ -1,11 +0,0 @@
# ctime.awk
#
# awk version of C ctime(3) function
function ctime(ts, format)
{
format = "%a %b %d %H:%M:%S %Z %Y"
if (ts == 0)
ts = systime() # use current time as default
return strftime(format, ts)
}

View File

@@ -1,30 +0,0 @@
SuperStrict
' Threading tutorial 1:
' A basic loading thread
' a threadable function
' threadable functions must return an Object and take 1 object as input, they don't need to be used
Function loadResources:Object(in:Object)
Print "Starting a child thread..."
For Local counter:Int = 0 Until 20 ' just a loop to make stuff happen
Print "Pretending to load resource " + counter
Delay(300) ' just to make this take some time like loading a real resource would
Next
Print "Child thread complete."
End Function
'####### Main code starts here
' Create a thread with loadResources() and Null as it's input object value
Local loadingThread:TThread = CreateThread(loadResources, Null)
Print "Starting the main loop..."
While(ThreadRunning(loadingThread)) ' as long as that child thread is still running...
Print "Waiting on our resources..."
Delay(100) ' we could do whatever we want here...
Wend
Print "Main loop complete."

View File

@@ -1,200 +0,0 @@
$ SET SOURCEFORMAT"FREE"
IDENTIFICATION DIVISION.
PROGRAM-ID. ACME99.
AUTHOR. Michael Coughlan.
*CS431399R-EXAM.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT ORDER-FILE ASSIGN TO "ORDERS.DAT"
ORGANIZATION IS LINE SEQUENTIAL.
SELECT STOCK-FILE ASSIGN TO "STOCK.DAT"
ORGANIZATION IS RELATIVE
ACCESS MODE IS DYNAMIC
RELATIVE KEY IS STOCK-REC-POINTER-WB
FILE STATUS IS STOCK-STATUS-WB.
SELECT MANF-FILE ASSIGN TO "MANF.DAT"
ORGANIZATION IS INDEXED
ACCESS MODE IS RANDOM
RECORD KEY IS MANF-CODE-FC
ALTERNATE RECORD KEY IS MANF-NAME-FC
WITH DUPLICATES
FILE STATUS IS MANF-STATUS-WB.
DATA DIVISION.
FILE SECTION.
FD ORDER-FILE.
01 ORDER-REC-FA.
02 ITEM-DESC-FA PIC X(30).
02 MANF-NAME-FA PIC X(30).
02 QTY-REQUIRED-FA PIC 9(6).
02 COST-OF-ITEMS-FA PIC 9(5)V99.
02 POSTAGE-FA PIC 99V99.
FD STOCK-FILE.
01 STOCK-REC-FB.
02 STOCK-NUM-FB PIC 9(5).
02 MANF-CODE-FB PIC X(4).
02 ITEM-DESC-FB PIC X(30).
02 QTY-IN-STOCK-FB PIC 9(6).
02 REORDER-LEVEL-FB PIC 999.
02 REORDER-QTY-FB PIC 9(6).
02 ITEM-COST-FB PIC 9(5).
02 ITEM-WEIGHT-FB PIC 9(5).
02 ON-ORDER-FB PIC X.
88 NOT-ON-ORDER VALUE "N".
88 ON-ORDER VALUE "Y".
FD MANF-FILE.
01 MANF-REC-FC.
02 MANF-CODE-FC PIC X(4).
02 MANF-NAME-FC PIC X(30).
02 MANF-ADDRESS-FC PIC X(70).
WORKING-STORAGE SECTION.
01 CALL-ITEMS-WA.
02 POST-CHARGE-WA PIC 99V99.
02 POST-NUM-WA PIC 99.
01 FILE-DATA-WB.
02 STOCK-REC-POINTER-WB PIC 9(5).
02 STOCK-STATUS-WB PIC XX.
02 MANF-STATUS-WB PIC XX.
02 FILLER PIC 9 VALUE 0.
88 END-OF-FILE VALUE 1.
01 UNSTRING-DATA-WC.
02 UNSTRING-POINTER-WC PIC 99.
88 END-OF-ADDRESS VALUE 71.
02 HOLD-STRING-WC PIC X(10).
02 COUNTY-WC PIC X(9).
88 NORTHERN-COUNTY
VALUE "ANTRIM", "ARMAGH", "DERRY", "DOWN",
"FERMANAGH", "TYRONE".
02 COUNTRY-WC PIC X(10).
88 EEC-COUNTRY
VALUE "AUSTRIA", "BELGIUM", "DENMARK", "ENGLAND", "FINLAND",
"FRANCE", "GERMANY", "GREECE", "IRELAND", "ITALY",
"LUXEMBOURG", "PORTUGAL", "SCOTLAND", "SPAIN",
"SWEDEN", "WALES".
88 IRELAND VALUE "IRELAND".
02 COUNTRY-FLAGS-WC PIC 9.
88 OTHER-EEC VALUE 1.
88 REPUBLIC VALUE 0.
01 POSTAGE-DATA-WD.
02 TOTAL-WEIGHT-WD PIC 9(5).
88 OVER-WEIGHT VALUE 50001 THRU 99999.
PROCEDURE DIVISION.
CREATE-REORDER-FILE.
OPEN I-O STOCK-FILE.
OPEN INPUT MANF-FILE.
OPEN OUTPUT ORDER-FILE.
READ STOCK-FILE NEXT RECORD
AT END SET END-OF-FILE TO TRUE
END-READ.
PERFORM UNTIL END-OF-FILE
IF (QTY-IN-STOCK-FB NOT GREATER THAN REORDER-LEVEL-FB)
AND (NOT-ON-ORDER)
PERFORM CREATE-REORDER-RECORD
PERFORM UPDATE-STOCK-RECORD
END-IF
READ STOCK-FILE NEXT RECORD
AT END SET END-OF-FILE TO TRUE
END-READ
END-PERFORM.
CLOSE STOCK-FILE, MANF-FILE, ORDER-FILE.
STOP RUN.
CREATE-REORDER-RECORD.
MOVE MANF-CODE-FB TO MANF-CODE-FC.
READ MANF-FILE
KEY IS MANF-CODE-FC
INVALID KEY DISPLAY "CRR MANF STATUS = "
MANF-STATUS-WB "CODE = " MANF-CODE-FC
END-READ.
PERFORM EXTRACT-ADDRESS-ITEMS.
MOVE ZEROS TO POSTAGE-FA, COST-OF-ITEMS-FA.
IF EEC-COUNTRY
PERFORM GET-POSTAGE
MULTIPLY ITEM-COST-FB BY REORDER-QTY-FB
GIVING COST-OF-ITEMS-FA
MOVE POST-CHARGE-WA TO POSTAGE-FA
END-IF.
MOVE ITEM-DESC-FB TO ITEM-DESC-FA.
MOVE MANF-NAME-FC TO MANF-NAME-FA.
MOVE REORDER-QTY-FB TO QTY-REQUIRED-FA.
WRITE ORDER-REC-FA.
GET-POSTAGE.
IF IRELAND AND NOT NORTHERN-COUNTY
SET REPUBLIC TO TRUE
ELSE
SET OTHER-EEC TO TRUE
END-IF.
MULTIPLY ITEM-WEIGHT-FB BY REORDER-QTY-FB
GIVING TOTAL-WEIGHT-WD
ON SIZE ERROR MOVE 99999 TO TOTAL-WEIGHT-WD.
EVALUATE TOTAL-WEIGHT-WD ALSO REPUBLIC ALSO OTHER-EEC
WHEN 1 THRU 500 ALSO TRUE ALSO FALSE MOVE 1 TO POST-NUM-WA
WHEN 1 THRU 500 ALSO FALSE ALSO TRUE MOVE 2 TO POST-NUM-WA
WHEN 501 THRU 1000 ALSO TRUE ALSO FALSE MOVE 3 TO POST-NUM-WA
WHEN 501 THRU 1000 ALSO FALSE ALSO TRUE MOVE 4 TO POST-NUM-WA
WHEN 1001 THRU 3000 ALSO TRUE ALSO FALSE MOVE 5 TO POST-NUM-WA
WHEN 1001 THRU 3000 ALSO FALSE ALSO TRUE MOVE 6 TO POST-NUM-WA
WHEN 3001 THRU 5000 ALSO TRUE ALSO FALSE MOVE 7 TO POST-NUM-WA
WHEN 3001 THRU 5000 ALSO FALSE ALSO TRUE MOVE 8 TO POST-NUM-WA
WHEN 5001 THRU 10000 ALSO TRUE ALSO FALSE MOVE 9 TO POST-NUM-WA
WHEN 5001 THRU 10000 ALSO FALSE ALSO TRUE MOVE 10 TO POST-NUM-WA
WHEN 10001 THRU 50000 ALSO TRUE ALSO FALSE MOVE 11 TO POST-NUM-WA
WHEN 10001 THRU 50000 ALSO FALSE ALSO TRUE MOVE 12 TO POST-NUM-WA
WHEN 50001 THRU 99999 ALSO ANY ALSO ANY MOVE ZEROS
TO POST-CHARGE-WA
WHEN OTHER DISPLAY "EVALUATE WRONG:- WEIGHT = " TOTAL-WEIGHT-WD
" COUNTRY FLAG = " COUNTRY-FLAGS-WC
END-EVALUATE.
IF NOT OVER-WEIGHT
CALL "POSTAGE-RATE"
USING BY CONTENT POST-NUM-WA
BY REFERENCE POST-CHARGE-WA
END-IF.
UPDATE-STOCK-RECORD.
MOVE "Y" TO ON-ORDER-FB.
REWRITE STOCK-REC-FB
INVALID KEY DISPLAY "STOCK REWRITE STATUS = " STOCK-STATUS-WB
END-REWRITE.
EXTRACT-ADDRESS-ITEMS.
MOVE 1 TO UNSTRING-POINTER-WC.
PERFORM UNTIL END-OF-ADDRESS
MOVE HOLD-STRING-WC TO COUNTY-WC
UNSTRING MANF-ADDRESS-FC DELIMITED BY ","
INTO HOLD-STRING-WC
WITH POINTER UNSTRING-POINTER-WC
END-PERFORM.
MOVE HOLD-STRING-WC TO COUNTRY-WC.
*debugging displays
DISPLAY "COUNTY = " COUNTY-WC.
DISPLAY "COUNTRY = " COUNTRY-WC.

View File

@@ -1,132 +0,0 @@
$ SET SOURCEFORMAT"FREE"
IDENTIFICATION DIVISION.
PROGRAM-ID. DriverProg.
AUTHOR. Michael Coughlan.
* This program demonstrates the use of the CALL verb
* it calls three external sub-programs that help to demonstrate
* some of the features of the CALL.
* The "MultiplyNums" sub-program takes five parameters. The first two
* are the numbers to be multiplied, the second two are strings to
* demonstrate that strings can be passed as parameters and the
* last is the returned result of multiplying the two numbers.
* The "Fickle" sub-program demonstrates a program that exhibits
* State Memory.
* The "Steadfast" sub-program demonstrates how a sub-program that
* uses the IS INITIAL phrase can avoid State Memory.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 UserNumber PIC 99.
01 PrnResult PIC 9(6).
* field declared as COMP cannot be DISPLAYed
* it is necessary to move it to a DISPLAY field.
* DISPLAY is the default value for a field and
* need not be declared.
* Parameters must be either 01-level's or elementry
* data-items.
01 Parameters.
02 Number1 PIC 9(3).
02 Number2 PIC 9(3).
02 FirstString PIC X(19) VALUE "First parameter = ".
02 SecondString PIC X(19) VALUE "Second parameter = ".
02 Result PIC 9(6) COMP.
* I've made this a COMP field to demonstrate that COMP
* items can be passed as parameters but a COMP field cannot
* be DISPLAYed and so is moved to a DISPLAY field before DISPLAYing it.
PROCEDURE DIVISION.
Begin.
PERFORM CallMultiplyNums.
PERFORM CallFickle
PERFORM CallSteadfast
PERFORM MakeFickleSteadfast.
STOP RUN.
CallMultiplyNums.
DISPLAY "Input 2 numbers (3 digits each) to be multiplied"
DISPLAY "First number - " WITH NO ADVANCING
ACCEPT Number1
DISPLAY "Second number - " WITH NO ADVANCING
ACCEPT Number2.
DISPLAY "The first string is " FirstString.
DISPLAY "The second string is " SecondString.
DISPLAY ">>>>>>>>> Calling the sub-program now".
CALL "MultiplyNums"
USING BY CONTENT Number1, Number2, FirstString,
BY REFERENCE SecondString, Result.
* The USING phrase specifies the parameters to be passed to the
* sub-program. The order of the parameters is important as the
* sub-program recognizes them by relative location not by name
*
* Parameters should be passed BY CONTENT when you are not expecting
* them to get a value from the called program. We have not passed
* SecondString by content and you can see that its value is
* overwritten by the called program.
DISPLAY "Back in the main program now <<<<<<<<<<<".
MOVE Result to PrnResult.
DISPLAY Number1 " multiplied by " Number2 " is = " PrnResult.
DISPLAY "The first string is " FirstString.
DISPLAY "The second string is " SecondString.
CallFickle.
DISPLAY SPACE
DISPLAY "------------------- Calling Fickle ---------"
MOVE 10 TO UserNumber
CALL "Fickle" USING BY CONTENT UserNumber
MOVE 10 TO UserNumber
CALL "Fickle" USING BY CONTENT UserNumber
MOVE 10 TO UserNumber
CALL "Fickle" USING BY CONTENT UserNumber.
* Every time I call Fickle with the same value
* produces a different result. This is because
* it remembers its state from one call to the next.
* It has "State Memory".
CallSteadFast.
DISPLAY SPACE
DISPLAY "------------------- Calling Steadfast ---------"
MOVE 10 TO UserNumber
CALL "Steadfast" USING BY CONTENT UserNumber
MOVE 10 TO UserNumber
CALL "Steadfast" USING BY CONTENT UserNumber
MOVE 10 TO UserNumber
CALL "Steadfast" USING BY CONTENT UserNumber.
* Every time I call Steadfast with the same value
* it produces the same result. We have eliminated
* State Memory by using the IS INITIAL phrase in
* Steadfast
MakeFickleSteadfast.
DISPLAY SPACE
DISPLAY "----- Making fickle act like Steadfast -------"
CANCEL "Fickle"
MOVE 10 TO UserNumber
CALL "Fickle" USING BY CONTENT UserNumber
CANCEL "Fickle"
MOVE 10 TO UserNumber
CALL "Fickle" USING BY CONTENT UserNumber
CANCEL "Fickle"
MOVE 10 TO UserNumber
CALL "Fickle" USING BY CONTENT UserNumber.
* We can make Fickle act like Steadfast by using
* the CANCEL verb to set it into its initial state
* each time we call it

View File

@@ -1,251 +0,0 @@
Robot = require '../robot'
Adapter = require '../adapter'
HTTPS = require 'https'
EventEmitter = require('events').EventEmitter
class Campfire extends Adapter
send: (user, strings...) ->
if strings.length > 0
@bot.Room(user.room).speak strings.shift(), (err, data) =>
@robot.logger.error "Campfire error: #{err}" if err?
@send user, strings...
reply: (user, strings...) ->
@send user, strings.map((str) -> "#{user.name}: #{str}")...
topic: (user, strings...) ->
@bot.Room(user.room).topic strings.join(" / "), (err, data) =>
@robot.logger.error "Campfire error: #{err}" if err?
run: ->
self = @
options =
token: process.env.HUBOT_CAMPFIRE_TOKEN
rooms: process.env.HUBOT_CAMPFIRE_ROOMS
account: process.env.HUBOT_CAMPFIRE_ACCOUNT
bot = new CampfireStreaming(options, @robot)
withAuthor = (callback) -> (id, created, room, user, body) ->
bot.User user, (err, userData) ->
if userData.user
author = self.userForId(userData.user.id, userData.user)
self.robot.brain.data.users[userData.user.id].name = userData.user.name
self.robot.brain.data.users[userData.user.id].email_address = userData.user.email_address
author.room = room
callback id, created, room, user, body, author
bot.on "TextMessage", withAuthor (id, created, room, user, body, author) ->
unless bot.info.id == author.id
self.receive new Robot.TextMessage(author, body)
bot.on "EnterMessage", withAuthor (id, created, room, user, body, author) ->
unless bot.info.id == author.id
self.receive new Robot.EnterMessage(author)
bot.on "LeaveMessage", withAuthor (id, created, room, user, body, author) ->
unless bot.info.id == author.id
self.receive new Robot.LeaveMessage(author)
bot.Me (err, data) ->
bot.info = data.user
bot.name = bot.info.name
for roomId in bot.rooms
do (roomId) ->
bot.Room(roomId).join (err, callback) ->
bot.Room(roomId).listen()
bot.on "reconnect", (roomId) ->
bot.Room(roomId).join (err, callback) ->
bot.Room(roomId).listen()
@bot = bot
self.emit "connected"
exports.use = (robot) ->
new Campfire robot
class CampfireStreaming extends EventEmitter
constructor: (options, @robot) ->
unless options.token? and options.rooms? and options.account?
@robot.logger.error "Not enough parameters provided. I Need a token, rooms and account"
process.exit(1)
@token = options.token
@rooms = options.rooms.split(",")
@account = options.account
@domain = @account + ".campfirenow.com"
@authorization = "Basic " + new Buffer("#{@token}:x").toString("base64")
Rooms: (callback) ->
@get "/rooms", callback
User: (id, callback) ->
@get "/users/#{id}", callback
Me: (callback) ->
@get "/users/me", callback
Room: (id) ->
self = @
logger = @robot.logger
show: (callback) ->
self.post "/room/#{id}", "", callback
join: (callback) ->
self.post "/room/#{id}/join", "", callback
leave: (callback) ->
self.post "/room/#{id}/leave", "", callback
lock: (callback) ->
self.post "/room/#{id}/lock", "", callback
unlock: (callback) ->
self.post "/room/#{id}/unlock", "", callback
# say things to this channel on behalf of the token user
paste: (text, callback) ->
@message text, "PasteMessage", callback
topic: (text, callback) ->
body = {room: {topic: text}}
self.put "/room/#{id}", body, callback
sound: (text, callback) ->
@message text, "SoundMessage", callback
speak: (text, callback) ->
body = { message: { "body":text } }
self.post "/room/#{id}/speak", body, callback
message: (text, type, callback) ->
body = { message: { "body":text, "type":type } }
self.post "/room/#{id}/speak", body, callback
# listen for activity in channels
listen: ->
headers =
"Host" : "streaming.campfirenow.com"
"Authorization" : self.authorization
options =
"agent" : false
"host" : "streaming.campfirenow.com"
"port" : 443
"path" : "/room/#{id}/live.json"
"method" : "GET"
"headers": headers
request = HTTPS.request options, (response) ->
response.setEncoding("utf8")
buf = ''
response.on "data", (chunk) ->
if chunk is ' '
# campfire api sends a ' ' heartbeat every 3s
else if chunk.match(/^\s*Access Denied/)
# errors are not json formatted
logger.error "Campfire error on room #{id}: #{chunk}"
else
# api uses newline terminated json payloads
# buffer across tcp packets and parse out lines
buf += chunk
while (offset = buf.indexOf("\r")) > -1
part = buf.substr(0, offset)
buf = buf.substr(offset + 1)
if part
try
data = JSON.parse part
self.emit data.type, data.id, data.created_at, data.room_id, data.user_id, data.body
catch err
logger.error "Campfire error: #{err}"
response.on "end", ->
logger.error "Streaming connection closed for room #{id}. :("
setTimeout (->
self.emit "reconnect", id
), 5000
response.on "error", (err) ->
logger.error "Campfire response error: #{err}"
request.on "error", (err) ->
logger.error "Campfire request error: #{err}"
request.end()
# Convenience HTTP Methods for posting on behalf of the token"d user
get: (path, callback) ->
@request "GET", path, null, callback
post: (path, body, callback) ->
@request "POST", path, body, callback
put: (path, body, callback) ->
@request "PUT", path, body, callback
request: (method, path, body, callback) ->
logger = @robot.logger
headers =
"Authorization" : @authorization
"Host" : @domain
"Content-Type" : "application/json"
options =
"agent" : false
"host" : @domain
"port" : 443
"path" : path
"method" : method
"headers": headers
if method is "POST" || method is "PUT"
if typeof(body) isnt "string"
body = JSON.stringify body
body = new Buffer(body)
options.headers["Content-Length"] = body.length
request = HTTPS.request options, (response) ->
data = ""
response.on "data", (chunk) ->
data += chunk
response.on "end", ->
if response.statusCode >= 400
switch response.statusCode
when 401
throw new Error "Invalid access token provided, campfire refused the authentication"
else
logger.error "Campfire error: #{response.statusCode}"
try
callback null, JSON.parse(data)
catch err
callback null, data or { }
response.on "error", (err) ->
logger.error "Campfire response error: #{err}"
callback err, { }
if method is "POST" || method is "PUT"
request.end(body, 'binary')
else
request.end()
request.on "error", (err) ->
logger.error "Campfire request error: #{err}"

View File

@@ -1,588 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: sw=4 ts=4 et :
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Chris Jones <jones.chris.g@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_DeadlockDetector_h
#define mozilla_DeadlockDetector_h
#include <stdlib.h>
#include "plhash.h"
#include "prlock.h"
#include "nsTArray.h"
#ifdef NS_TRACE_MALLOC
# include "nsTraceMalloc.h"
#endif // ifdef NS_TRACE_MALLOC
namespace mozilla {
// FIXME bug 456272: split this off into a convenience API on top of
// nsStackWalk?
class NS_COM_GLUE CallStack
{
private:
#ifdef NS_TRACE_MALLOC
typedef nsTMStackTraceID callstack_id;
// needs to be a macro to avoid disturbing the backtrace
# define NS_GET_BACKTRACE() NS_TraceMallocGetStackTrace()
#else
typedef void* callstack_id;
# define NS_GET_BACKTRACE() 0
#endif // ifdef NS_TRACE_MALLOC
callstack_id mCallStack;
public:
/**
* CallStack
* *ALWAYS* *ALWAYS* *ALWAYS* call this with no arguments. This
* constructor takes an argument *ONLY* so that |GET_BACKTRACE()|
* can be evaluated in the stack frame of the caller, rather than
* that of the constructor.
*
* *BEWARE*: this means that calling this constructor with no
* arguments is not the same as a "default, do-nothing"
* constructor: it *will* construct a backtrace. This can cause
* unexpected performance issues.
*/
CallStack(const callstack_id aCallStack = NS_GET_BACKTRACE()) :
mCallStack(aCallStack)
{
}
CallStack(const CallStack& aFrom) :
mCallStack(aFrom.mCallStack)
{
}
CallStack& operator=(const CallStack& aFrom)
{
mCallStack = aFrom.mCallStack;
return *this;
}
bool operator==(const CallStack& aOther) const
{
return mCallStack == aOther.mCallStack;
}
bool operator!=(const CallStack& aOther) const
{
return mCallStack != aOther.mCallStack;
}
// FIXME bug 456272: if this is split off,
// NS_TraceMallocPrintStackTrace should be modified to print into
// an nsACString
void Print(FILE* f) const
{
#ifdef NS_TRACE_MALLOC
if (this != &kNone && mCallStack) {
NS_TraceMallocPrintStackTrace(f, mCallStack);
return;
}
#endif
fputs(" [stack trace unavailable]\n", f);
}
/** The "null" callstack. */
static const CallStack kNone;
};
/**
* DeadlockDetector
*
* The following is an approximate description of how the deadlock detector
* works.
*
* The deadlock detector ensures that all blocking resources are
* acquired according to a partial order P. One type of blocking
* resource is a lock. If a lock l1 is acquired (locked) before l2,
* then we say that |l1 <_P l2|. The detector flags an error if two
* locks l1 and l2 have an inconsistent ordering in P; that is, if
* both |l1 <_P l2| and |l2 <_P l1|. This is a potential error
* because a thread acquiring l1,l2 according to the first order might
* race with a thread acquiring them according to the second order.
* If this happens under the right conditions, then the acquisitions
* will deadlock.
*
* This deadlock detector doesn't know at compile-time what P is. So,
* it tries to discover the order at run time. More precisely, it
* finds <i>some</i> order P, then tries to find chains of resource
* acquisitions that violate P. An example acquisition sequence, and
* the orders they impose, is
* l1.lock() // current chain: [ l1 ]
* // order: { }
*
* l2.lock() // current chain: [ l1, l2 ]
* // order: { l1 <_P l2 }
*
* l3.lock() // current chain: [ l1, l2, l3 ]
* // order: { l1 <_P l2, l2 <_P l3, l1 <_P l3 }
* // (note: <_P is transitive, so also |l1 <_P l3|)
*
* l2.unlock() // current chain: [ l1, l3 ]
* // order: { l1 <_P l2, l2 <_P l3, l1 <_P l3 }
* // (note: it's OK, but weird, that l2 was unlocked out
* // of order. we still have l1 <_P l3).
*
* l2.lock() // current chain: [ l1, l3, l2 ]
* // order: { l1 <_P l2, l2 <_P l3, l1 <_P l3,
* l3 <_P l2 (!!!) }
* BEEP BEEP! Here the detector will flag a potential error, since
* l2 and l3 were used inconsistently (and potentially in ways that
* would deadlock).
*/
template <typename T>
class DeadlockDetector
{
public:
/**
* ResourceAcquisition
* Consists simply of a resource and the calling context from
* which it was acquired. We pack this information together so
* that it can be returned back to the caller when a potential
* deadlock has been found.
*/
struct ResourceAcquisition
{
const T* mResource;
CallStack mCallContext;
ResourceAcquisition(
const T* aResource,
const CallStack aCallContext=CallStack::kNone) :
mResource(aResource),
mCallContext(aCallContext)
{
}
ResourceAcquisition(const ResourceAcquisition& aFrom) :
mResource(aFrom.mResource),
mCallContext(aFrom.mCallContext)
{
}
ResourceAcquisition& operator=(const ResourceAcquisition& aFrom)
{
mResource = aFrom.mResource;
mCallContext = aFrom.mCallContext;
return *this;
}
};
typedef nsTArray<ResourceAcquisition> ResourceAcquisitionArray;
private:
typedef nsTArray<PLHashEntry*> HashEntryArray;
typedef typename HashEntryArray::index_type index_type;
typedef typename HashEntryArray::size_type size_type;
enum {
NoIndex = HashEntryArray::NoIndex
};
/**
* Value type for the ordering table. Contains the other
* resources on which an ordering constraint |key < other|
* exists. The catch is that we also store the calling context at
* which the other resource was acquired; this improves the
* quality of error messages when potential deadlock is detected.
*/
struct OrderingEntry
{
OrderingEntry() :
mFirstSeen(CallStack::kNone),
mOrderedLT() // FIXME bug 456272: set to empirical
{ // dep size?
}
~OrderingEntry()
{
}
CallStack mFirstSeen; // first site from which the resource appeared
HashEntryArray mOrderedLT; // this <_o Other
};
static void* TableAlloc(void* /*pool*/, PRSize size)
{
return operator new(size);
}
static void TableFree(void* /*pool*/, void* item)
{
operator delete(item);
}
static PLHashEntry* EntryAlloc(void* /*pool*/, const void* key)
{
return new PLHashEntry;
}
static void EntryFree(void* /*pool*/, PLHashEntry* entry, PRUintn flag)
{
delete static_cast<T*>(const_cast<void*>(entry->key));
delete static_cast<OrderingEntry*>(entry->value);
entry->value = 0;
if (HT_FREE_ENTRY == flag)
delete entry;
}
static PLHashNumber HashKey(const void* aKey)
{
return NS_PTR_TO_INT32(aKey) >> 2;
}
static const PLHashAllocOps kAllocOps;
// Hash table "interface" the rest of the code should use
PLHashEntry** GetEntry(const T* aKey)
{
return PL_HashTableRawLookup(mOrdering, HashKey(aKey), aKey);
}
void PutEntry(T* aKey)
{
PL_HashTableAdd(mOrdering, aKey, new OrderingEntry());
}
// XXX need these helper methods because OrderingEntry doesn't have
// XXX access to underlying PLHashEntry
/**
* Add the order |aFirst <_o aSecond|.
*
* WARNING: this does not check whether it's sane to add this
* order. In the "best" bad case, when this order already exists,
* adding it anyway may unnecessarily result in O(n^2) space. In
* the "worst" bad case, adding it anyway will cause
* |InTransitiveClosure()| to diverge.
*/
void AddOrder(PLHashEntry* aLT, PLHashEntry* aGT)
{
static_cast<OrderingEntry*>(aLT->value)->mOrderedLT
.InsertElementSorted(aGT);
}
/**
* Return true iff the order |aFirst < aSecond| has been
* *explicitly* added.
*
* Does not consider transitivity.
*/
bool IsOrdered(const PLHashEntry* aFirst, const PLHashEntry* aSecond)
const
{
return NoIndex !=
static_cast<const OrderingEntry*>(aFirst->value)->mOrderedLT
.BinaryIndexOf(aSecond);
}
/**
* Return a pointer to the array of all elements "that" for
* which the order |this < that| has been explicitly added.
*
* NOTE: this does *not* consider transitive orderings.
*/
PLHashEntry* const* GetOrders(const PLHashEntry* aEntry) const
{
return static_cast<const OrderingEntry*>(aEntry->value)->mOrderedLT
.Elements();
}
/**
* Return the number of elements "that" for which the order
* |this < that| has been explicitly added.
*
* NOTE: this does *not* consider transitive orderings.
*/
size_type NumOrders(const PLHashEntry* aEntry) const
{
return static_cast<const OrderingEntry*>(aEntry->value)->mOrderedLT
.Length();
}
/** Make a ResourceAcquisition out of |aEntry|. */
ResourceAcquisition MakeResourceAcquisition(const PLHashEntry* aEntry)
const
{
return ResourceAcquisition(
static_cast<const T*>(aEntry->key),
static_cast<const OrderingEntry*>(aEntry->value)->mFirstSeen);
}
// Throwaway RAII lock to make the following code safer.
struct PRAutoLock
{
PRAutoLock(PRLock* aLock) : mLock(aLock) { PR_Lock(mLock); }
~PRAutoLock() { PR_Unlock(mLock); }
PRLock* mLock;
};
public:
static const PRUint32 kDefaultNumBuckets;
/**
* DeadlockDetector
* Create a new deadlock detector.
*
* @param aNumResourcesGuess Guess at approximate number of resources
* that will be checked.
*/
DeadlockDetector(PRUint32 aNumResourcesGuess = kDefaultNumBuckets)
{
mOrdering = PL_NewHashTable(aNumResourcesGuess,
HashKey,
PL_CompareValues, PL_CompareValues,
&kAllocOps, 0);
if (!mOrdering)
NS_RUNTIMEABORT("couldn't initialize resource ordering table");
mLock = PR_NewLock();
if (!mLock)
NS_RUNTIMEABORT("couldn't allocate deadlock detector lock");
}
/**
* ~DeadlockDetector
*
* *NOT* thread safe.
*/
~DeadlockDetector()
{
PL_HashTableDestroy(mOrdering);
PR_DestroyLock(mLock);
}
/**
* Add
* Make the deadlock detector aware of |aResource|.
*
* WARNING: The deadlock detector owns |aResource|.
*
* Thread safe.
*
* @param aResource Resource to make deadlock detector aware of.
*/
void Add(T* aResource)
{
PRAutoLock _(mLock);
PutEntry(aResource);
}
// Nb: implementing a Remove() method makes the detector "more
// unsound." By removing a resource from the orderings, deadlocks
// may be missed that would otherwise have been found. However,
// removing resources possibly reduces the # of false positives,
// and additionally saves space. So it's a trade off; we have
// chosen to err on the side of caution and not implement Remove().
/**
* CheckAcquisition This method is called after acquiring |aLast|,
* but before trying to acquire |aProposed| from |aCallContext|.
* It determines whether actually trying to acquire |aProposed|
* will create problems. It is OK if |aLast| is NULL; this is
* interpreted as |aProposed| being the thread's first acquisition
* of its current chain.
*
* Iff acquiring |aProposed| may lead to deadlock for some thread
* interleaving (including the current one!), the cyclical
* dependency from which this was deduced is returned. Otherwise,
* 0 is returned.
*
* If a potential deadlock is detected and a resource cycle is
* returned, it is the *caller's* responsibility to free it.
*
* Thread safe.
*
* @param aLast Last resource acquired by calling thread (or 0).
* @param aProposed Resource calling thread proposes to acquire.
* @param aCallContext Calling context whence acquisiton request came.
*/
ResourceAcquisitionArray* CheckAcquisition(const T* aLast,
const T* aProposed,
const CallStack& aCallContext)
{
NS_ASSERTION(aProposed, "null resource");
PRAutoLock _(mLock);
PLHashEntry* second = *GetEntry(aProposed);
OrderingEntry* e = static_cast<OrderingEntry*>(second->value);
if (CallStack::kNone == e->mFirstSeen)
e->mFirstSeen = aCallContext;
if (!aLast)
// don't check if |0 < proposed|; just vamoose
return 0;
PLHashEntry* first = *GetEntry(aLast);
// this is the crux of the deadlock detector algorithm
if (first == second) {
// reflexive deadlock. fastpath b/c InTransitiveClosure is
// not applicable here.
ResourceAcquisitionArray* cycle = new ResourceAcquisitionArray();
if (!cycle)
NS_RUNTIMEABORT("can't allocate dep. cycle array");
cycle->AppendElement(MakeResourceAcquisition(first));
cycle->AppendElement(ResourceAcquisition(aProposed,
aCallContext));
return cycle;
}
if (InTransitiveClosure(first, second)) {
// we've already established |last < proposed|. all is well.
return 0;
}
if (InTransitiveClosure(second, first)) {
// the order |proposed < last| has been deduced, perhaps
// transitively. we're attempting to violate that
// constraint by acquiring resources in the order
// |last < proposed|, and thus we may deadlock under the
// right conditions.
ResourceAcquisitionArray* cycle = GetDeductionChain(second, first);
// show how acquiring |proposed| would complete the cycle
cycle->AppendElement(ResourceAcquisition(aProposed,
aCallContext));
return cycle;
}
// |last|, |proposed| are unordered according to our
// poset. this is fine, but we now need to add this
// ordering constraint.
AddOrder(first, second);
return 0;
}
/**
* Return true iff |aTarget| is in the transitive closure of |aStart|
* over the ordering relation `<_this'.
*
* @precondition |aStart != aTarget|
*/
bool InTransitiveClosure(const PLHashEntry* aStart,
const PLHashEntry* aTarget) const
{
if (IsOrdered(aStart, aTarget))
return true;
index_type i = 0;
size_type len = NumOrders(aStart);
for (const PLHashEntry* const* it = GetOrders(aStart);
i < len; ++i, ++it)
if (InTransitiveClosure(*it, aTarget))
return true;
return false;
}
/**
* Return an array of all resource acquisitions
* aStart <_this r1 <_this r2 <_ ... <_ aTarget
* from which |aStart <_this aTarget| was deduced, including
* |aStart| and |aTarget|.
*
* Nb: there may be multiple deductions of |aStart <_this
* aTarget|. This function returns the first ordering found by
* depth-first search.
*
* Nb: |InTransitiveClosure| could be replaced by this function.
* However, this one is more expensive because we record the DFS
* search stack on the heap whereas the other doesn't.
*
* @precondition |aStart != aTarget|
*/
ResourceAcquisitionArray* GetDeductionChain(
const PLHashEntry* aStart,
const PLHashEntry* aTarget)
{
ResourceAcquisitionArray* chain = new ResourceAcquisitionArray();
if (!chain)
NS_RUNTIMEABORT("can't allocate dep. cycle array");
chain->AppendElement(MakeResourceAcquisition(aStart));
NS_ASSERTION(GetDeductionChain_Helper(aStart, aTarget, chain),
"GetDeductionChain called when there's no deadlock");
return chain;
}
// precondition: |aStart != aTarget|
// invariant: |aStart| is the last element in |aChain|
bool GetDeductionChain_Helper(const PLHashEntry* aStart,
const PLHashEntry* aTarget,
ResourceAcquisitionArray* aChain)
{
if (IsOrdered(aStart, aTarget)) {
aChain->AppendElement(MakeResourceAcquisition(aTarget));
return true;
}
index_type i = 0;
size_type len = NumOrders(aStart);
for (const PLHashEntry* const* it = GetOrders(aStart);
i < len; ++i, ++it) {
aChain->AppendElement(MakeResourceAcquisition(*it));
if (GetDeductionChain_Helper(*it, aTarget, aChain))
return true;
aChain->RemoveElementAt(aChain->Length() - 1);
}
return false;
}
/**
* The partial order on resource acquisitions used by the deadlock
* detector.
*/
PLHashTable* mOrdering; // T* -> PLHashEntry<OrderingEntry>
/**
* Protects contentious methods.
* Nb: can't use mozilla::Mutex since we are used as its deadlock
* detector.
*/
PRLock* mLock;
DeadlockDetector(const DeadlockDetector& aDD);
DeadlockDetector& operator=(const DeadlockDetector& aDD);
};
template<typename T>
const PLHashAllocOps DeadlockDetector<T>::kAllocOps = {
DeadlockDetector<T>::TableAlloc, DeadlockDetector<T>::TableFree,
DeadlockDetector<T>::EntryAlloc, DeadlockDetector<T>::EntryFree
};
template<typename T>
// FIXME bug 456272: tune based on average workload
const PRUint32 DeadlockDetector<T>::kDefaultNumBuckets = 64;
} // namespace mozilla
#endif // ifndef mozilla_DeadlockDetector_h

View File

@@ -1,597 +0,0 @@
/* Test file for C++ language.
* Attempt to include as many aspects of the C++ language as possible.
* Do not include things tested in test.c since that shares the
* same language.
*
* $Id: test.cpp,v 1.22 2008/05/17 20:12:55 zappo Exp $
*
*/
/* An include test */
#include <stdio.h>
#include <cmath>
#include "c++-test.hh"
#include <c++-test.hh>
double var1 = 1.2;
int simple1(int a) {
}
struct foo1 {
int test;
};
struct foo2 : public foo1 {
const int foo21(int a, int b);
const int foo22(int a, int b) { return 1 }
};
/* Classes */
class class1 {
private:
int var11;
struct foo1 var12;
public:
int p_var11;
struct foo p_var12;
};
class i_class1 : public class1 {
private:
int var11;
struct foo var12;
public:
int p_var11;
struct foo p_var12;
};
class class2 {
private:
int var21;
struct foo var22;
public:
int p_var21;
struct foo p_var22;
};
class i_class2 : public class1, public class2 {
private:
int var21;
struct foo var22;
protected:
int pt_var21;
public:
int p_var21;
struct foo p_var22;
};
class class3 {
/* A class with strange things in it */
public:
class3(); /* A constructor */
enum embedded_foo_enum {
a, b, c
} embed1;
struct embedded_bar_struct {
int a;
int b;
} embed2;
class embedded_baz_class {
embedded_baz_class();
~embedded_baz_class();
} embed3;
~class3(); /* destructor */
/* Methods */
int method_for_class3(int a, char b);
int inline_method(int c) { return c; }
/* Operators */
class3& operator^= (const class3& something);
/* Funny declmods */
const class3 * const method_const_ptr_ptr(const int * const argconst) const = 0;
};
class3::class3()
{
/* Constructor outside the definition. */
}
int class3::method_for_class3(int a, char b)
{
}
int class3::method1_for_class3( int a, int &b)
{
int cvariablename;
class3 fooy[];
class3 moose = new class3;
// Complktion testing line should find external members.
a = fooy[1].me ;
b = cv ;
if (fooy.emb) {
simple1(c);
}
cos(10);
abs(10);
return 1;
}
char class3::method2_for_class3( int a, int b) throw ( exception1 )
{
return 'a';
}
void *class3::method3_for_class3( int a, int b) throw ( exception1, exception2 )
{
int q = a;
return "Moose";
}
void *class3::method31_for_class3( int a, int b) throw ( )
{
int q = a;
return "Moose";
}
void *class3::method4_for_class3( int a, int b) reentrant
{
class3 ct;
ct.method5_for_class3(1,a);
pritf();
}
/*
* A method on class3.
*/
void *class3::method5_for_class3( int a, int b) const
{
}
/*
* Namespace parsing tests
*/
namespace NS {
class class_in_namespace {
int equiv(const NS::class_in_namespace *) const;
};
}
int NS::class_in_namespace::equiv(const NS::class_in_namespace *cin) const
{
return 0;
}
// Stuff Klaus found.
// Inheritance w/out a specifying for public.
class class4 : class1 {
// Pure virtual methods.
void virtual print () const = 0;
public:
// The whacky constructor type
class4()
try : class1(args)
{
// constructor body
}
catch ()
{
}
};
class class5 : public virtual class4 {
// Virtual inheritance
};
class class6 : class1 {
// Mutable
mutable int i;
};
/* Namespaces */
namespace namespace1 {
void ns_method1() { }
class n_class1 {
public:
void method11(int a) { }
};
/* This shouldn't parse due to missing semicolon. */
class _n_class2 : public n_class1 {
void n_c2_method1(int a, int b) { }
};
// Macros in the namespace
#define NSMACRO 1
// Template in the namespace
template<class T> T nsti1(const Foo& foo);
template<> int nsti1<int>(const Foo& foo);
}
namespace namespace2 {
using namespace1::n_class1;
}
/* Initializers */
void tinitializers1(): inita1(False),
inita2(False)
{
inita1= 1;
}
/* How about Extern C type things. */
int funny_prototype(int ,int b,float c)
{
}
extern "C"
int extern_c_1(int a, int b)
{
funny_prototype(1,2,3.4);
printf("Moose", );
return 1;
}
extern "C" {
int extern_c_2(int a, int b)
{
return 1;
}
}
// Some operator stuff
class Action
{
// Problems!! operator() and operator[] can not be parsed with semantic
// 1.4.2 but with latest c.by
virtual void operator()(int i, char *p ) = 0;
virtual String& operator[]() = 0;
virtual void operator!() = 0;
virtual void operator->() = 0;
virtual T& operator+=();
virtual T& operator*();
virtual T& operator*=();
};
// class with namespace qualified parents
class Multiinherit : public virtual POA::Parent,
public virtual POA::Parent1,
Parent
{
private:
int i;
public:
Multiinherit();
~Multiinherit();
// method with a list of qualified exceptions
void* throwtest()
throw(Exception0,
Testnamespace::Exception1,
Testnamespace::Excpetion2,
Testnamespace::testnamespace1::Exception3);
};
void*
Multiinherit::throwtest()
throw (Exception0,
Testnamespace::Exception1,
Testnamespace::Excpetion2,
Testnamespace::testnamespace1::Exception3)
{
return;
}
// Jens Rock <jens.rock@asamnet.de>: Nested classes or structs defined
// outside of the containing class/struct.
class container
{
public:
struct contained;
container();
~container();
};
struct container::contained
{
public:
contained();
~contained();
};
/*
* Ok, how about some template stuff.
*/
template <class CT, class container = vector<CT> >
const CT& max (const CT& a, const CT& b)
{
return a < b ? b : a;
}
// Arne Schmitz found this one
std::vector<int> &a, &b, &c;
class TemplateUsingClass
{
typedef TestClassMap::iterator iterator;
typedef map<long, long> TestClassMap;
// typedefs with const and volatile
typedef const map<long, long> const_TestClassMap;
typedef TestClassMap<string>::iterator volatile volatile_iterator;
map<int, int> mapclassvarthingy;
};
template<class T> T ti1(const Foo& foo);
template<> int ti1<int>(const Foo& foo);
// -----------------------------------
// Now some namespace and related stuff
// -----------------------------------
using CORBA::LEX::get_token;
using Namespace1;
using namespace POA::std;
using namespace Test;
namespace Parser
{
namespace
{
using Lexer::get_test;
string str = "";
}
namespace XXX
{
class Foobar : public virtual POA::Parent,
public virtual POA::Parent1,
private POA::list<fact>,
private map<string>
{
int i;
list <shared_ptr<item> >::const_iterator l;
public:
Foobar();
~Foobar();
};
}
void test_function(int i);
};
// unnamed namespaces - even nested
namespace
{
namespace
{
using Lexer::get_test;
string str = "";
class FooClass
{
FooClass();
};
}
// some builtin types
long long ll = 0;
long double d = 0.0;
unsigned test;
unsigned long int **uli = 0;
signed si = 0;
signed short ss = 0;
short int i = 0;
long int li = 0;
// expressions with namespace/class-qualifyiers
ORB_var cGlobalOrb = ORB::_nil();
ORB_var1 cGlobalOrb1 = ORB::_test;
class Testclass
{
#define TEST 0
ini i;
public:
Testclass();
~Testclass();
};
static void test_function(unsigned int i);
};
// outside method implementations which should be grouped to type Test
XXX&
Test::waiting()
{
return;
}
void
Test::print()
{
return;
}
// outside method implementations with namespaces which should be grouped to
// their complete (incl. namespace) types
void*
Parser::XXX::Foobar::wait(int i, const char const * const * p)
{
return;
}
void*
Namespace1::Test::wait1(int i)
{
return;
}
int
Namespace1::Test::waiting(int i)
{
return;
}
// a class with some outside implementations which should all be grouped to
// this class declaration
class ClassWithExternals
{
private:
int i;
public:
ClassWithExternals();
~ClassWithExternals();
void non_nil();
};
// Foobar is not displayed; seems that semantic tries to add this to the class
// Foobar but can not find/display it, because contained in the namespace above.
void
Foobar::non_nil()
{
return;
}
// are correctly grouped to the ClassWithExternals class
void
ClassWithExternals::non_nil()
{
String s = "lödfjg dlfgkdlfkgjdl";
return;
}
ClassWithExternals::ClassWithExternals()
{
return;
}
void
ClassWithExternals::~ClassWithExternals()
{
return;
}
// -------------------------------
// Now some macro and define stuff
// -------------------------------
#define TEST 0
#define TEST1 "String"
// The first backslash makes this macro unmatched syntax with semantic 1.4.2!
// With flexing \+newline as nothing all is working fine!
#define MZK_ENTER(METHOD) \
{ \
CzkMethodLog lMethodLog(METHOD,"Framework");\
}
#define ZK_ASSERTM(METHOD,ASSERTION,MESSAGE) \
{ if(!(ASSERTION))\
{\
std::ostringstream lMesgStream; \
lMesgStream << "Assertion failed: " \
<< MESSAGE; \
CzkLogManager::doLog(CzkLogManager::FATAL,"",METHOD, \
"Assert",lMesgStream); \
assert(ASSERTION);\
}\
}
// Test if not newline-backslashes are handled correctly
string s = "My \"quoted\" string";
// parsed fine as macro
#define FOO (arg) method(arg, "foo");
// With semantic 1.4.2 this parsed as macro BAR *and* function method.
// With latest c.bnf at least one-liner macros can be parsed correctly.
#define BAR (arg) CzkMessageLog method(arg, "bar");
// some const and volatile stuff
char * p1 = "Hello"; // 1. variable Pointer, variable Data
const char * p2 = "Hello"; // 2. variable pointer, constant data
char * const p3 = "Hello"; // 3. constant pointer, variable data
const char * const p4 = "Hello"; // 4. constant pointer, constant data
// Case 2 and 4 can exchange first "const" and "char"
char const * p21 = "Hello"; // variable pointer, constant data
char const * const p41 = "Hello"; // constant pointer, constant data
char volatile a = 0; // a volatile char
void foo(bar const &arg); // a reference to a const bar
int foobar(bar const * const p); // a const pointer to a const bar
int foobar(bar const volatile * const p); // a const pointer to a const bar
int foobar3(char* p); // a const pointer to a const bar
// Should not be parsed because this is invalid code
int const & const r3 = i;
boolean i = 0;
boolean & r1 = i;
boolean const & r2 = i;
// const * sequences can be very long in C++ ;-)
char const * const * const * const * ppp;
// complex function declarationen with named pointer-arguments
const char** foobar1(volatile char const * const **p);
const char** foobar11(volatile Test::Namespace::Char<char*> const * const **p);
// complex function declarationen with unnamed pointer-arguments
const char* foobar2(const char***);
const char* foobar21(const Test::Namespace::Char<char>***);
// string literal parsing even with wchar_t
char const *p = "string1";
char const *q = "string1" "str\"ing2" "string3";
wchar_t testc = L'a';
wchar_t const *wp = L"string with a \" in it";
wchar_t const *wq = L"string \n\t\"test" L"string2";
wchar_t const *wr = L"string L";

View File

@@ -1,8 +0,0 @@
#include <pd/http/client.H>
namespace phantom { namespace io_stream { namespace proto_http {
namespace handler_bts {
} // namespace handler_bts
}}} // namespace phantom::io_stream::proto_http

File diff suppressed because it is too large Load Diff

View File

@@ -1,195 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 et tw=99:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
* May 28, 2008.
*
* The Initial Developer of the Original Code is
* Brendan Eich <brendan@mozilla.org>
*
* Contributor(s):
* Andreas Gal <gal@mozilla.com>
* Mike Shaver <shaver@mozilla.org>
* David Anderson <danderson@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nanojit/nanojit.h"
using namespace nanojit;
void*
nanojit::Allocator::allocChunk(size_t nbytes)
{
VMAllocator *vma = (VMAllocator*)this;
JS_ASSERT(!vma->outOfMemory());
void *p = malloc(nbytes);
if (!p) {
JS_ASSERT(nbytes < sizeof(vma->mReserve));
vma->mOutOfMemory = true;
p = (void*) &vma->mReserve[0];
}
vma->mSize += nbytes;
return p;
}
void
nanojit::Allocator::freeChunk(void *p) {
VMAllocator *vma = (VMAllocator*)this;
if (p != &vma->mReserve[0])
free(p);
}
void
nanojit::Allocator::postReset() {
VMAllocator *vma = (VMAllocator*)this;
vma->mOutOfMemory = false;
vma->mSize = 0;
}
void
nanojit::StackFilter::getTops(LIns* guard, int& spTop, int& rpTop)
{
VMSideExit* e = (VMSideExit*)guard->record()->exit;
spTop = e->sp_adj;
rpTop = e->rp_adj;
}
class AdjustCallerGlobalTypesVisitor : public SlotVisitorBase
{
TraceRecorder &mRecorder;
JSContext *mCx;
nanojit::LirBuffer *mLirbuf;
nanojit::LirWriter *mLir;
JSTraceType *mTypeMap;
public:
AdjustCallerGlobalTypesVisitor(TraceRecorder &recorder,
JSTraceType *typeMap) :
mRecorder(recorder),
mCx(mRecorder.cx),
mLirbuf(mRecorder.lirbuf),
mLir(mRecorder.lir),
mTypeMap(typeMap)
{}
JSTraceType* getTypeMap()
{
return mTypeMap;
}
JS_REQUIRES_STACK JS_ALWAYS_INLINE void
visitGlobalSlot(jsval *vp, unsigned n, unsigned slot) {
LIns *ins = mRecorder.get(vp);
bool isPromote = isPromoteInt(ins);
if (isPromote && *mTypeMap == TT_DOUBLE) {
mLir->insStorei(mRecorder.get(vp), mLirbuf->state,
mRecorder.nativeGlobalOffset(vp));
/*
* Aggressively undo speculation so the inner tree will compile
* if this fails.
*/
oracle.markGlobalSlotUndemotable(mCx, slot);
}
JS_ASSERT(!(!isPromote && *mTypeMap == TT_INT32));
++mTypeMap;
}
};
class AdjustCallerStackTypesVisitor : public SlotVisitorBase
{
TraceRecorder &mRecorder;
JSContext *mCx;
nanojit::LirBuffer *mLirbuf;
nanojit::LirWriter *mLir;
unsigned mSlotnum;
JSTraceType *mTypeMap;
public:
AdjustCallerStackTypesVisitor(TraceRecorder &recorder,
JSTraceType *typeMap) :
mRecorder(recorder),
mCx(mRecorder.cx),
mLirbuf(mRecorder.lirbuf),
mLir(mRecorder.lir),
mSlotnum(0),
mTypeMap(typeMap)
{}
JSTraceType* getTypeMap()
{
return mTypeMap;
}
JS_REQUIRES_STACK JS_ALWAYS_INLINE bool
visitStackSlots(jsval *vp, size_t count, JSStackFrame* fp) {
for (size_t i = 0; i < count; ++i) {
LIns *ins = mRecorder.get(vp);
bool isPromote = isPromoteInt(ins);
if (isPromote && *mTypeMap == TT_DOUBLE) {
mLir->insStorei(mRecorder.get(vp), mLirbuf->sp,
-mRecorder.treeInfo->nativeStackBase +
mRecorder.nativeStackOffset(vp));
/*
* Aggressively undo speculation so the inner tree will compile
* if this fails.
*/
oracle.markStackSlotUndemotable(mCx, mSlotnum);
}
JS_ASSERT(!(!isPromote && *mTypeMap == TT_INT32));
++vp;
++mTypeMap;
++mSlotnum;
}
return true;
}
};
#if defined NJ_VERBOSE
void
nanojit::LirNameMap::formatGuard(LIns *i, char *out)
{
VMSideExit *x;
x = (VMSideExit *)i->record()->exit;
sprintf(out,
"%s: %s %s -> pc=%p imacpc=%p sp%+ld rp%+ld (GuardID=%03d)",
formatRef(i),
lirNames[i->opcode()],
i->oprnd1() ? formatRef(i->oprnd1()) : "",
(void *)x->pc,
(void *)x->imacpc,
(long int)x->sp_adj,
(long int)x->rp_adj,
i->record()->profGuardID);
}
#endif

View File

@@ -1,15 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
NS_IMETHODIMP
nsThreadClassInfo::GetClassDescription(
char **result,
int foo,
bool blah
)
{
*result = nsnull;
return NS_OK;
}
int foo;

View File

@@ -1,6 +0,0 @@
void*
Foo::bar(int i,
const char const * const * p)
{
return;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,310 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is IBM Corporation.
* Portions created by IBM Corporation are Copyright (C) 2003
* IBM Corporation. All Rights Reserved.
*
* Contributor(s):
* IBM Corp.
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIEventTarget.h"
#include "nsIServiceManager.h"
#include "nsIObserverService.h"
#include "nsIObserver.h"
#include "nsAutoLock.h"
#include "nsCOMPtr.h"
#include "prclist.h"
#include "prlog.h"
#if defined(PR_LOGGING)
//
// NSPR_LOG_MODULES=nsIOThreadPool:5
//
static PRLogModuleInfo *gIOThreadPoolLog = nsnull;
#endif
#define LOG(args) PR_LOG(gIOThreadPoolLog, PR_LOG_DEBUG, args)
// this number specifies the maximum number of threads.
#define MAX_THREADS 4
// this number specifies how long to wait before killing an idle thread. it's
// important to pick a large enough value here to minimize thread churn.
#define IDLE_TIMEOUT PR_SecondsToInterval(60)
#define PLEVENT_FROM_LINK(_link) \
((PLEvent*) ((char*) (_link) - offsetof(PLEvent, link)))
//-----------------------------------------------------------------------------
// pool of joinable threads used for general purpose i/o tasks
//
// the main entry point to this class is nsIEventTarget. events posted to
// the thread pool are dispatched on one of the threads. a variable number
// of threads are maintained. the threads die off if they remain idle for
// more than THREAD_IDLE_TIMEOUT. the thread pool shuts down when it receives
// the "xpcom-shutdown" event.
//-----------------------------------------------------------------------------
class nsIOThreadPool : public nsIEventTarget
, public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIEVENTTARGET
NS_DECL_NSIOBSERVER
nsresult Init();
void Shutdown();
private:
virtual ~nsIOThreadPool();
PR_STATIC_CALLBACK(void) ThreadFunc(void *);
// mLock protects all (exceptions during Init and Shutdown)
PRLock *mLock;
PRCondVar *mIdleThreadCV; // notified to wake up an idle thread
PRCondVar *mExitThreadCV; // notified when a thread exits
PRUint32 mNumThreads; // number of active + idle threads
PRUint32 mNumIdleThreads; // number of idle threads
PRCList mEventQ; // queue of PLEvent structs
PRBool mShutdown; // set to true if shutting down
};
NS_IMPL_THREADSAFE_ISUPPORTS2(nsIOThreadPool, nsIEventTarget, nsIObserver)
nsresult
nsIOThreadPool::Init()
{
#if defined(PR_LOGGING)
if (!gIOThreadPoolLog)
gIOThreadPoolLog = PR_NewLogModule("nsIOThreadPool");
#endif
mNumThreads = 0;
mNumIdleThreads = 0;
mShutdown = PR_FALSE;
mLock = PR_NewLock();
if (!mLock)
return NS_ERROR_OUT_OF_MEMORY;
mIdleThreadCV = PR_NewCondVar(mLock);
if (!mIdleThreadCV)
return NS_ERROR_OUT_OF_MEMORY;
mExitThreadCV = PR_NewCondVar(mLock);
if (!mExitThreadCV)
return NS_ERROR_OUT_OF_MEMORY;
PR_INIT_CLIST(&mEventQ);
// we want to shutdown the i/o thread pool at xpcom-shutdown time...
nsCOMPtr<nsIObserverService> os = do_GetService("@mozilla.org/observer-service;1");
if (os)
os->AddObserver(this, "xpcom-shutdown", PR_FALSE);
return NS_OK;
}
nsIOThreadPool::~nsIOThreadPool()
{
LOG(("Destroying nsIOThreadPool @%p\n", this));
#ifdef DEBUG
NS_ASSERTION(PR_CLIST_IS_EMPTY(&mEventQ), "leaking events");
NS_ASSERTION(mNumThreads == 0, "leaking thread(s)");
#endif
if (mIdleThreadCV)
PR_DestroyCondVar(mIdleThreadCV);
if (mExitThreadCV)
PR_DestroyCondVar(mExitThreadCV);
if (mLock)
PR_DestroyLock(mLock);
}
void
nsIOThreadPool::Shutdown()
{
LOG(("nsIOThreadPool::Shutdown\n"));
// synchronize with background threads...
{
nsAutoLock lock(mLock);
mShutdown = PR_TRUE;
PR_NotifyAllCondVar(mIdleThreadCV);
while (mNumThreads != 0)
PR_WaitCondVar(mExitThreadCV, PR_INTERVAL_NO_TIMEOUT);
}
}
NS_IMETHODIMP
nsIOThreadPool::PostEvent(PLEvent *event)
{
LOG(("nsIOThreadPool::PostEvent [event=%p]\n", event));
nsAutoLock lock(mLock);
// if we are shutting down, then prevent additional events from being
// added to the queue...
if (mShutdown)
return NS_ERROR_UNEXPECTED;
nsresult rv = NS_OK;
PR_APPEND_LINK(&event->link, &mEventQ);
// now, look for an available idle thread...
if (mNumIdleThreads)
PR_NotifyCondVar(mIdleThreadCV); // wake up an idle thread
// or, try to create a new thread unless we have reached our maximum...
else if (mNumThreads < MAX_THREADS) {
NS_ADDREF_THIS(); // the thread owns a reference to us
mNumThreads++;
PRThread *thread = PR_CreateThread(PR_USER_THREAD,
ThreadFunc,
this,
PR_PRIORITY_NORMAL,
PR_GLOBAL_THREAD,
PR_UNJOINABLE_THREAD,
0);
if (!thread) {
NS_RELEASE_THIS();
mNumThreads--;
rv = NS_ERROR_OUT_OF_MEMORY;
}
}
// else, we expect one of the active threads to process the event queue.
return rv;
}
NS_IMETHODIMP
nsIOThreadPool::IsOnCurrentThread(PRBool *result)
{
// no one should be calling this method. if this assertion gets hit,
// then we need to think carefully about what this method should be
// returning.
NS_NOTREACHED("nsIOThreadPool::IsOnCurrentThread");
// fudging this a bit since we actually cover several threads...
*result = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsIOThreadPool::Observe(nsISupports *, const char *topic, const PRUnichar *)
{
NS_ASSERTION(strcmp(topic, "xpcom-shutdown") == 0, "unexpected topic");
Shutdown();
return NS_OK;
}
void
nsIOThreadPool::ThreadFunc(void *arg)
{
nsIOThreadPool *pool = (nsIOThreadPool *) arg;
LOG(("entering ThreadFunc\n"));
{
nsAutoLock lock(pool->mLock);
for (;;) {
PRIntervalTime start = PR_IntervalNow(), timeout = IDLE_TIMEOUT;
//
// wait for one or more of the following to occur:
// (1) the event queue has an event to process
// (2) the shutdown flag has been set
// (3) the thread has been idle for too long
//
// PR_WaitCondVar will return when any of these conditions is true.
//
while (PR_CLIST_IS_EMPTY(&pool->mEventQ) && !pool->mShutdown) {
pool->mNumIdleThreads++;
PR_WaitCondVar(pool->mIdleThreadCV, timeout);
pool->mNumIdleThreads--;
PRIntervalTime delta = PR_IntervalNow() - start;
if (delta >= timeout)
break;
timeout -= delta;
start += delta;
}
// if the queue is still empty, then kill this thread (either we
// are shutting down or the thread exceeded the idle timeout)...
if (PR_CLIST_IS_EMPTY(&pool->mEventQ))
break;
// handle one event at a time: we don't want this one thread to hog
// all the events while other threads may be able to help out ;-)
do {
PLEvent *event = PLEVENT_FROM_LINK(PR_LIST_HEAD(&pool->mEventQ));
PR_REMOVE_AND_INIT_LINK(&event->link);
LOG(("event:%p\n", event));
// release lock!
lock.unlock();
PL_HandleEvent(event);
lock.lock();
}
while (!PR_CLIST_IS_EMPTY(&pool->mEventQ));
}
// thread is going away...
pool->mNumThreads--;
PR_NotifyCondVar(pool->mExitThreadCV);
}
// release our reference to the pool
NS_RELEASE(pool);
LOG(("leaving ThreadFunc\n"));
}
//-----------------------------------------------------------------------------
NS_METHOD
net_NewIOThreadPool(nsISupports *outer, REFNSIID iid, void **result)
{
nsIOThreadPool *pool = new nsIOThreadPool();
if (!pool)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(pool);
nsresult rv = pool->Init();
if (NS_SUCCEEDED(rv))
rv = pool->QueryInterface(iid, result);
NS_RELEASE(pool);
return rv;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,702 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla code.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Darin Fisher <darin@meer.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "timelog.h"
#include "nsThread.h"
#include "nsThreadManager.h"
#include "nsIClassInfoImpl.h"
#include "nsIProgrammingLanguage.h"
#include "nsAutoLock.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "prlog.h"
#include "nsThreadUtilsInternal.h"
#ifdef PR_LOGGING
static PRLogModuleInfo *sLog = PR_NewLogModule("nsThread");
#endif
#define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args)
NS_DECL_CI_INTERFACE_GETTER(nsThread)
nsIThreadObserver* nsThread::sGlobalObserver;
//-----------------------------------------------------------------------------
// Because we do not have our own nsIFactory, we have to implement nsIClassInfo
// somewhat manually.
class nsThreadClassInfo : public nsIClassInfo {
public:
NS_DECL_ISUPPORTS_INHERITED // no mRefCnt
NS_DECL_NSICLASSINFO
nsThreadClassInfo() {}
};
static nsThreadClassInfo sThreadClassInfo;
NS_IMETHODIMP_(nsrefcnt) nsThreadClassInfo::AddRef() { return 2; }
NS_IMETHODIMP_(nsrefcnt) nsThreadClassInfo::Release() { return 1; }
NS_IMPL_QUERY_INTERFACE1(nsThreadClassInfo, nsIClassInfo)
NS_IMETHODIMP
nsThreadClassInfo::GetInterfaces(PRUint32 *count, nsIID ***array)
{
return NS_CI_INTERFACE_GETTER_NAME(nsThread)(count, array);
}
NS_IMETHODIMP
nsThreadClassInfo::GetHelperForLanguage(PRUint32 lang, nsISupports **result)
{
*result = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsThreadClassInfo::GetContractID(char **result)
{
*result = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsThreadClassInfo::GetClassDescription(char **result)
{
*result = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsThreadClassInfo::GetClassID(nsCID **result)
{
*result = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsThreadClassInfo::GetImplementationLanguage(PRUint32 *result)
{
*result = nsIProgrammingLanguage::CPLUSPLUS;
return NS_OK;
}
NS_IMETHODIMP
nsThreadClassInfo::GetFlags(PRUint32 *result)
{
*result = THREADSAFE;
return NS_OK;
}
NS_IMETHODIMP
nsThreadClassInfo::GetClassIDNoAlloc(nsCID *result)
{
return NS_ERROR_NOT_AVAILABLE;
}
//-----------------------------------------------------------------------------
NS_IMPL_THREADSAFE_ADDREF(nsThread)
NS_IMPL_THREADSAFE_RELEASE(nsThread)
NS_INTERFACE_MAP_BEGIN(nsThread)
NS_INTERFACE_MAP_ENTRY(nsIThread)
NS_INTERFACE_MAP_ENTRY(nsIThreadInternal)
NS_INTERFACE_MAP_ENTRY(nsIEventTarget)
NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIThread)
if (aIID.Equals(NS_GET_IID(nsIClassInfo))) {
foundInterface = static_cast<nsIClassInfo*>(&sThreadClassInfo);
} else
NS_INTERFACE_MAP_END
NS_IMPL_CI_INTERFACE_GETTER4(nsThread, nsIThread, nsIThreadInternal,
nsIEventTarget, nsISupportsPriority)
//-----------------------------------------------------------------------------
class nsThreadStartupEvent : public nsRunnable {
public:
// Create a new thread startup object.
static nsThreadStartupEvent *Create() {
nsThreadStartupEvent *startup = new nsThreadStartupEvent();
if (startup && startup->mMon)
return startup;
// Allocation failure
delete startup;
return nsnull;
}
// This method does not return until the thread startup object is in the
// completion state.
void Wait() {
if (mInitialized) // Maybe avoid locking...
return;
nsAutoMonitor mon(mMon);
while (!mInitialized)
mon.Wait();
}
// This method needs to be public to support older compilers (xlC_r on AIX).
// It should be called directly as this class type is reference counted.
virtual ~nsThreadStartupEvent() {
if (mMon)
nsAutoMonitor::DestroyMonitor(mMon);
}
private:
NS_IMETHOD Run() {
nsAutoMonitor mon(mMon);
mInitialized = PR_TRUE;
mon.Notify();
return NS_OK;
}
nsThreadStartupEvent()
: mMon(nsAutoMonitor::NewMonitor("xpcom.threadstartup"))
, mInitialized(PR_FALSE) {
}
PRMonitor *mMon;
PRBool mInitialized;
};
//-----------------------------------------------------------------------------
// This event is responsible for notifying nsThread::Shutdown that it is time
// to call PR_JoinThread.
class nsThreadShutdownAckEvent : public nsRunnable {
public:
nsThreadShutdownAckEvent(nsThreadShutdownContext *ctx)
: mShutdownContext(ctx) {
}
NS_IMETHOD Run() {
mShutdownContext->shutdownAck = PR_TRUE;
return NS_OK;
}
private:
nsThreadShutdownContext *mShutdownContext;
};
// This event is responsible for setting mShutdownContext
class nsThreadShutdownEvent : public nsRunnable {
public:
nsThreadShutdownEvent(nsThread *thr, nsThreadShutdownContext *ctx)
: mThread(thr), mShutdownContext(ctx) {
}
NS_IMETHOD Run() {
mThread->mShutdownContext = mShutdownContext;
return NS_OK;
}
private:
nsRefPtr<nsThread> mThread;
fprintf(logfp, "%s.%09ld: New Thread (%p)\n", out.str, out.nsec, (void *)self);
// Inform the ThreadManager
nsThreadManager::get()->RegisterCurrentThread(self);
// Wait for and process startup event
nsCOMPtr<nsIRunnable> event;
if (!self->GetEvent(PR_TRUE, getter_AddRefs(event))) {
NS_WARNING("failed waiting for thread startup event");
return;
}
event->Run(); // unblocks nsThread::Init
event = nsnull;
// Now, process incoming events...
while (!self->ShuttingDown())
NS_ProcessNextEvent(self);
// Do NS_ProcessPendingEvents but with special handling to set
// mEventsAreDoomed atomically with the removal of the last event. The key
// invariant here is that we will never permit PutEvent to succeed if the
// event would be left in the queue after our final call to
// NS_ProcessPendingEvents.
while (PR_TRUE) {
{
nsAutoLock lock(self->mLock);
if (!self->mEvents->HasPendingEvent()) {
// No events in the queue, so we will stop now. Don't let any more
// events be added, since they won't be processed. It is critical
// that no PutEvent can occur between testing that the event queue is
// empty and setting mEventsAreDoomed!
self->mEventsAreDoomed = PR_TRUE;
break;
}
}
NS_ProcessPendingEvents(self);
}
// Inform the threadmanager that this thread is going away
nsThreadManager::get()->UnregisterCurrentThread(self);
// Dispatch shutdown ACK
event = new nsThreadShutdownAckEvent(self->mShutdownContext);
self->mShutdownContext->joiningThread->Dispatch(event, NS_DISPATCH_NORMAL);
// Release any observer of the thread here.
self->SetObserver(nsnull);
NS_RELEASE(self);
}
//-----------------------------------------------------------------------------
nsThread::nsThread()
: mLock(PR_NewLock())
, mEvents(&mEventsRoot)
, mPriority(PRIORITY_NORMAL)
, mThread(nsnull)
, mRunningEvent(0)
, mShutdownContext(nsnull)
, mShutdownRequired(PR_FALSE)
, mEventsAreDoomed(PR_FALSE)
{
}
nsThread::~nsThread()
{
if (mLock)
PR_DestroyLock(mLock);
}
nsresult
nsThread::Init()
{
NS_ENSURE_TRUE(mLock, NS_ERROR_OUT_OF_MEMORY);
struct logtime out;
get_log_time(&out);
fprintf(logfp, "%s.%09ld: Thread (%p) Init() start\n", out.str, out.nsec, (void *)this);
// spawn thread and wait until it is fully setup
nsRefPtr<nsThreadStartupEvent> startup = nsThreadStartupEvent::Create();
NS_ENSURE_TRUE(startup, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF_THIS();
mShutdownRequired = PR_TRUE;
// ThreadFunc is responsible for setting mThread
PRThread *thr = PR_CreateThread(PR_USER_THREAD, ThreadFunc, this,
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
PR_JOINABLE_THREAD, 0);
if (!thr) {
NS_RELEASE_THIS();
return NS_ERROR_OUT_OF_MEMORY;
}
// ThreadFunc will wait for this event to be run before it tries to access
// mThread. By delaying insertion of this event into the queue, we ensure
// that mThread is set properly.
{
nsAutoLock lock(mLock);
mEvents->PutEvent(startup);
}
// Wait for thread to call ThreadManager::SetupCurrentThread, which completes
// initialization of ThreadFunc.
startup->Wait();
get_log_time(&out);
fprintf(logfp, "%s.%09ld: Thread (%p) Init() end\n", out.str, out.nsec, (void *)this);
return NS_OK;
}
nsresult
nsThread::InitCurrentThread()
{
NS_ENSURE_TRUE(mLock, NS_ERROR_OUT_OF_MEMORY);
mThread = PR_GetCurrentThread();
nsThreadManager::get()->RegisterCurrentThread(this);
return NS_OK;
}
nsresult
nsThread::PutEvent(nsIRunnable *event)
{
{
nsAutoLock lock(mLock);
if (mEventsAreDoomed) {
NS_WARNING("An event was posted to a thread that will never run it (rejected)");
return NS_ERROR_UNEXPECTED;
}
if (!mEvents->PutEvent(event))
return NS_ERROR_OUT_OF_MEMORY;
}
nsCOMPtr<nsIThreadObserver> obs = GetObserver();
if (obs)
obs->OnDispatchedEvent(this);
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsIEventTarget
NS_IMETHODIMP
nsThread::Dispatch(nsIRunnable *event, PRUint32 flags)
{
LOG(("THRD(%p) Dispatch [%p %x]\n", this, event, flags));
NS_ENSURE_ARG_POINTER(event);
if (flags & DISPATCH_SYNC) {
nsThread *thread = nsThreadManager::get()->GetCurrentThread();
NS_ENSURE_STATE(thread);
// XXX we should be able to do something better here... we should
// be able to monitor the slot occupied by this event and use
// that to tell us when the event has been processed.
nsRefPtr<nsThreadSyncDispatch> wrapper =
new nsThreadSyncDispatch(thread, event);
if (!wrapper)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = PutEvent(wrapper);
// Don't wait for the event to finish if we didn't dispatch it...
if (NS_FAILED(rv))
return rv;
while (wrapper->IsPending())
NS_ProcessNextEvent(thread);
return rv;
}
NS_ASSERTION(flags == NS_DISPATCH_NORMAL, "unexpected dispatch flags");
return PutEvent(event);
}
NS_IMETHODIMP
nsThread::IsOnCurrentThread(PRBool *result)
{
*result = (PR_GetCurrentThread() == mThread);
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsIThread
NS_IMETHODIMP
nsThread::GetPRThread(PRThread **result)
{
*result = mThread;
return NS_OK;
}
NS_IMETHODIMP
nsThread::Shutdown()
{
LOG(("THRD(%p) shutdown\n", this));
// XXX If we make this warn, then we hit that warning at xpcom shutdown while
// shutting down a thread in a thread pool. That happens b/c the thread
// in the thread pool is already shutdown by the thread manager.
if (!mThread)
return NS_OK;
NS_ENSURE_STATE(mThread != PR_GetCurrentThread());
// Prevent multiple calls to this method
{
nsAutoLock lock(mLock);
if (!mShutdownRequired)
return NS_ERROR_UNEXPECTED;
mShutdownRequired = PR_FALSE;
}
nsThreadShutdownContext context;
context.joiningThread = nsThreadManager::get()->GetCurrentThread();
context.shutdownAck = PR_FALSE;
// Set mShutdownContext and wake up the thread in case it is waiting for
// events to process.
nsCOMPtr<nsIRunnable> event = new nsThreadShutdownEvent(this, &context);
if (!event)
return NS_ERROR_OUT_OF_MEMORY;
// XXXroc What if posting the event fails due to OOM?
PutEvent(event);
// We could still end up with other events being added after the shutdown
// task, but that's okay because we process pending events in ThreadFunc
// after setting mShutdownContext just before exiting.
// Process events on the current thread until we receive a shutdown ACK.
while (!context.shutdownAck)
NS_ProcessNextEvent(context.joiningThread);
// Now, it should be safe to join without fear of dead-locking.
PR_JoinThread(mThread);
mThread = nsnull;
#ifdef DEBUG
{
nsAutoLock lock(mLock);
NS_ASSERTION(!mObserver, "Should have been cleared at shutdown!");
}
#endif
return NS_OK;
}
NS_IMETHODIMP
nsThread::HasPendingEvents(PRBool *result)
{
NS_ENSURE_STATE(PR_GetCurrentThread() == mThread);
*result = mEvents->GetEvent(PR_FALSE, nsnull);
return NS_OK;
}
NS_IMETHODIMP
nsThread::ProcessNextEvent(PRBool mayWait, PRBool *result)
{
struct logtime out;
get_log_time(&out);
fprintf(logfp, "%s.%09ld: Thread (%p) ProcessNextEvent [%u %u]\n",
out.str,
out.nsec,
(void *)this,
mayWait,
mRunningEvent);
LOG(("THRD(%p) ProcessNextEvent [%u %u]\n", this, mayWait, mRunningEvent));
NS_ENSURE_STATE(PR_GetCurrentThread() == mThread);
PRBool notifyGlobalObserver = (sGlobalObserver != nsnull);
if (notifyGlobalObserver)
sGlobalObserver->OnProcessNextEvent(this, mayWait && !ShuttingDown(),
mRunningEvent);
nsCOMPtr<nsIThreadObserver> obs = mObserver;
if (obs)
obs->OnProcessNextEvent(this, mayWait && !ShuttingDown(), mRunningEvent);
++mRunningEvent;
nsresult rv = NS_OK;
{
// Scope for |event| to make sure that its destructor fires while
// mRunningEvent has been incremented, since that destructor can
// also do work.
// If we are shutting down, then do not wait for new events.
nsCOMPtr<nsIRunnable> event;
mEvents->GetEvent(mayWait && !ShuttingDown(), getter_AddRefs(event));
*result = (event.get() != nsnull);
if (event) {
get_log_time(&out);
fprintf(logfp, "%s.%09ld: Thread (%p) running [%p]\n",
out.str,
out.nsec,
(void *)this,
(void *)event.get());
LOG(("THRD(%p) running [%p]\n", this, event.get()));
event->Run();
} else if (mayWait) {
NS_ASSERTION(ShuttingDown(),
"This should only happen when shutting down");
rv = NS_ERROR_UNEXPECTED;
}
get_log_time(&out);
fprintf(logfp, "%s.%09ld: Thread (%p) running finished [%p]\n",
out.str,
out.nsec,
(void *)this,
(void *)event.get());
}
--mRunningEvent;
if (obs)
obs->AfterProcessNextEvent(this, mRunningEvent);
if (notifyGlobalObserver && sGlobalObserver)
sGlobalObserver->AfterProcessNextEvent(this, mRunningEvent);
return rv;
}
//-----------------------------------------------------------------------------
// nsISupportsPriority
NS_IMETHODIMP
nsThread::GetPriority(PRInt32 *priority)
{
*priority = mPriority;
return NS_OK;
}
NS_IMETHODIMP
nsThread::SetPriority(PRInt32 priority)
{
NS_ENSURE_STATE(mThread);
// NSPR defines the following four thread priorities:
// PR_PRIORITY_LOW
// PR_PRIORITY_NORMAL
// PR_PRIORITY_HIGH
// PR_PRIORITY_URGENT
// We map the priority values defined on nsISupportsPriority to these values.
mPriority = priority;
PRThreadPriority pri;
if (mPriority <= PRIORITY_HIGHEST) {
pri = PR_PRIORITY_URGENT;
} else if (mPriority < PRIORITY_NORMAL) {
pri = PR_PRIORITY_HIGH;
} else if (mPriority > PRIORITY_NORMAL) {
pri = PR_PRIORITY_LOW;
} else {
pri = PR_PRIORITY_NORMAL;
}
PR_SetThreadPriority(mThread, pri);
return NS_OK;
}
NS_IMETHODIMP
nsThread::AdjustPriority(PRInt32 delta)
{
return SetPriority(mPriority + delta);
}
//-----------------------------------------------------------------------------
// nsIThreadInternal
NS_IMETHODIMP
nsThread::GetObserver(nsIThreadObserver **obs)
{
nsAutoLock lock(mLock);
NS_IF_ADDREF(*obs = mObserver);
return NS_OK;
}
NS_IMETHODIMP
nsThread::SetObserver(nsIThreadObserver *obs)
{
NS_ENSURE_STATE(PR_GetCurrentThread() == mThread);
nsAutoLock lock(mLock);
mObserver = obs;
return NS_OK;
}
NS_IMETHODIMP
nsThread::PushEventQueue(nsIThreadEventFilter *filter)
{
nsChainedEventQueue *queue = new nsChainedEventQueue(filter);
if (!queue || !queue->IsInitialized()) {
delete queue;
return NS_ERROR_OUT_OF_MEMORY;
}
nsAutoLock lock(mLock);
queue->mNext = mEvents;
mEvents = queue;
return NS_OK;
}
NS_IMETHODIMP
nsThread::PopEventQueue()
{
nsAutoLock lock(mLock);
// Make sure we do not pop too many!
NS_ENSURE_STATE(mEvents != &mEventsRoot);
nsChainedEventQueue *queue = mEvents;
mEvents = mEvents->mNext;
nsCOMPtr<nsIRunnable> event;
while (queue->GetEvent(PR_FALSE, getter_AddRefs(event)))
mEvents->PutEvent(event);
delete queue;
return NS_OK;
}
PRBool
nsThread::nsChainedEventQueue::PutEvent(nsIRunnable *event)
{
PRBool val;
if (!mFilter || mFilter->AcceptEvent(event)) {
val = mQueue.PutEvent(event);
} else {
val = mNext->PutEvent(event);
}
return val;
}
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsThreadSyncDispatch::Run()
{
if (mSyncTask) {
mSyncTask->Run();
mSyncTask = nsnull;
// unblock the origin thread
mOrigin->Dispatch(this, NS_DISPATCH_NORMAL);
}
return NS_OK;
}
nsresult
NS_SetGlobalThreadObserver(nsIThreadObserver* aObserver)
{
if (aObserver && nsThread::sGlobalObserver) {
return NS_ERROR_NOT_AVAILABLE;
}
if (!NS_IsMainThread()) {
return NS_ERROR_UNEXPECTED;
}
nsThread::sGlobalObserver = aObserver;
return NS_OK;
}

View File

@@ -1,170 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla code.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Darin Fisher <darin@meer.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsThread_h__
#define nsThread_h__
#include "nsIThreadInternal.h"
#include "nsISupportsPriority.h"
#include "nsEventQueue.h"
#include "nsThreadUtils.h"
#include "nsString.h"
#include "nsAutoLock.h"
#include "nsAutoPtr.h"
// A native thread
class nsThread : public nsIThreadInternal, public nsISupportsPriority
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIEVENTTARGET
NS_DECL_NSITHREAD
NS_DECL_NSITHREADINTERNAL
NS_DECL_NSISUPPORTSPRIORITY
nsThread();
// Initialize this as a wrapper for a new PRThread.
nsresult Init();
// Initialize this as a wrapper for the current PRThread.
nsresult InitCurrentThread();
// The PRThread corresponding to this thread.
PRThread *GetPRThread() { return mThread; }
// If this flag is true, then the nsThread was created using
// nsIThreadManager::NewThread.
PRBool ShutdownRequired() { return mShutdownRequired; }
// The global thread observer
static nsIThreadObserver* sGlobalObserver;
private:
friend class nsThreadShutdownEvent;
~nsThread();
PRBool ShuttingDown() { return mShutdownContext != nsnull; }
static void ThreadFunc(void *arg);
// Helper
already_AddRefed<nsIThreadObserver> GetObserver() {
nsIThreadObserver *obs;
nsThread::GetObserver(&obs);
return already_AddRefed<nsIThreadObserver>(obs);
}
// Wrappers for event queue methods:
PRBool GetEvent(PRBool mayWait, nsIRunnable **event) {
return mEvents->GetEvent(mayWait, event);
}
nsresult PutEvent(nsIRunnable *event);
// Wrapper for nsEventQueue that supports chaining.
class nsChainedEventQueue {
public:
nsChainedEventQueue(nsIThreadEventFilter *filter = nsnull)
: mNext(nsnull), mFilter(filter) {
}
PRBool IsInitialized() {
return mQueue.IsInitialized();
}
PRBool GetEvent(PRBool mayWait, nsIRunnable **event) {
return mQueue.GetEvent(mayWait, event);
}
PRBool PutEvent(nsIRunnable *event);
PRBool HasPendingEvent() {
return mQueue.HasPendingEvent();
}
class nsChainedEventQueue *mNext;
private:
nsCOMPtr<nsIThreadEventFilter> mFilter;
nsEventQueue mQueue;
};
// This lock protects access to mObserver, mEvents and mEventsAreDoomed.
// All of those fields are only modified on the thread itself (never from
// another thread). This means that we can avoid holding the lock while
// using mObserver and mEvents on the thread itself. When calling PutEvent
// on mEvents, we have to hold the lock to synchronize with PopEventQueue.
PRLock *mLock;
nsCOMPtr<nsIThreadObserver> mObserver;
nsChainedEventQueue *mEvents; // never null
nsChainedEventQueue mEventsRoot;
PRInt32 mPriority;
PRThread *mThread;
PRUint32 mRunningEvent; // counter
struct nsThreadShutdownContext *mShutdownContext;
PRPackedBool mShutdownRequired;
PRPackedBool mShutdownPending;
// Set to true when events posted to this thread will never run.
PRPackedBool mEventsAreDoomed;
};
//-----------------------------------------------------------------------------
class nsThreadSyncDispatch : public nsRunnable {
public:
nsThreadSyncDispatch(nsIThread *origin, nsIRunnable *task)
: mOrigin(origin), mSyncTask(task) {
}
PRBool IsPending() {
return mSyncTask != nsnull;
}
private:
NS_DECL_NSIRUNNABLE
nsCOMPtr<nsIThread> mOrigin;
nsCOMPtr<nsIRunnable> mSyncTask;
};
#endif // nsThread_h__

View File

@@ -1,46 +0,0 @@
namespace {
struct nsThreadShutdownContext {
nsThread *joiningThread;
PRBool shutdownAck;
union {
int a;
int b;
union {
char f;
char g;
};
};
};
};
struct teststruct {
char foo;
union {
int x;
int y;
};
};
namespace
{
short int i = 0;
class Testclass
{
int j;
public:
Testclass();
~Testclass();
};
namespace
{
string str = "";
class FooClass
{
FooClass();
};
}
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,558 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <stdio.h>
#include "nsXPCOM.h"
#include "nsXPCOMCIDInternal.h"
#include "nsIComponentManager.h"
#include "nsIComponentRegistrar.h"
#include "nsIServiceManager.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsCOMArray.h"
#include "nscore.h"
#include "nspr.h"
#include "prmon.h"
#include "nsITestProxy.h"
#include "nsIRunnable.h"
#include "nsIProxyObjectManager.h"
#include "nsIThreadPool.h"
#include "nsXPCOMCIDInternal.h"
#include "nsComponentManagerUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
#include "prlog.h"
#ifdef PR_LOGGING
static PRLogModuleInfo *sLog = PR_NewLogModule("Test");
#define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args)
#else
#define LOG(args) printf args
#endif
namespace proxytests {
static nsresult
GetThreadFromPRThread(PRThread *prthread, nsIThread **result)
{
LOG(("TEST: GetThreadFromPRThread [%p]\n", prthread));
nsCOMPtr<nsIThreadManager> tm = do_GetService(NS_THREADMANAGER_CONTRACTID);
NS_ENSURE_STATE(tm);
return tm->GetThreadFromPRThread(prthread, result);
}
/***************************************************************************/
/* nsTestXPCFoo */
/***************************************************************************/
class nsTestXPCFoo : public nsITestProxy
{
NS_DECL_ISUPPORTS
NS_IMETHOD Test(PRInt32 p1, PRInt32 p2, PRInt32* retval);
NS_IMETHOD Test2();
NS_IMETHOD Test3(nsISupports *p1, nsISupports **p2);
nsTestXPCFoo();
};
nsTestXPCFoo::nsTestXPCFoo()
{
NS_ADDREF_THIS();
}
NS_IMPL_ISUPPORTS1(nsTestXPCFoo, nsITestProxy)
NS_IMETHODIMP nsTestXPCFoo::Test(PRInt32 p1, PRInt32 p2, PRInt32* retval)
{
LOG(("TEST: Thread (%d) Test Called successfully! Party on...\n", p1));
*retval = p1+p2;
return NS_OK;
}
NS_IMETHODIMP nsTestXPCFoo::Test2()
{
LOG(("TEST: The quick brown netscape jumped over the old lazy ie..\n"));
return NS_OK;
}
NS_IMETHODIMP nsTestXPCFoo::Test3(nsISupports *p1, nsISupports **p2)
{
if (p1 != nsnull)
{
nsITestProxy *test;
p1->QueryInterface(NS_GET_IID(nsITestProxy), (void**)&test);
test->Test2();
PRInt32 a;
test->Test( 1, 2, &a);
LOG(("TEST: \n1+2=%d\n",a));
}
*p2 = new nsTestXPCFoo();
return NS_OK;
}
/***************************************************************************/
/* nsTestXPCFoo2 */
/***************************************************************************/
class nsTestXPCFoo2 : public nsITestProxy
{
NS_DECL_ISUPPORTS
NS_IMETHOD Test(PRInt32 p1, PRInt32 p2, PRInt32* retval);
NS_IMETHOD Test2();
NS_IMETHOD Test3(nsISupports *p1, nsISupports **p2);
nsTestXPCFoo2();
};
nsTestXPCFoo2::nsTestXPCFoo2()
{
NS_ADDREF_THIS();
}
NS_IMPL_THREADSAFE_ISUPPORTS1(nsTestXPCFoo2, nsITestProxy)
NS_IMETHODIMP nsTestXPCFoo2::Test(PRInt32 p1, PRInt32 p2, PRInt32* retval)
{
LOG(("TEST: calling back to caller!\n"));
nsCOMPtr<nsIProxyObjectManager> manager =
do_GetService(NS_XPCOMPROXY_CONTRACTID);
LOG(("TEST: ProxyObjectManager: %p \n", (void *) manager.get()));
PR_ASSERT(manager);
nsCOMPtr<nsIThread> thread;
GetThreadFromPRThread((PRThread *) p1, getter_AddRefs(thread));
NS_ENSURE_STATE(thread);
nsCOMPtr<nsITestProxy> proxyObject;
manager->GetProxyForObject(thread, NS_GET_IID(nsITestProxy), this, NS_PROXY_SYNC, (void**)&proxyObject);
proxyObject->Test3(nsnull, nsnull);
LOG(("TEST: Deleting Proxy Object\n"));
return NS_OK;
}
NS_IMETHODIMP nsTestXPCFoo2::Test2()
{
LOG(("TEST: nsTestXPCFoo2::Test2() called\n"));
return NS_OK;
}
NS_IMETHODIMP nsTestXPCFoo2::Test3(nsISupports *p1, nsISupports **p2)
{
LOG(("TEST: Got called"));
return NS_OK;
}
#if 0
struct ArgsStruct {
nsIThread* thread;
PRInt32 threadNumber;
};
// This will create two objects both descendants of a single IID.
void TestCase_TwoClassesOneInterface(void *arg)
{
ArgsStruct *argsStruct = (ArgsStruct*) arg;
nsCOMPtr<nsIProxyObjectManager> manager =
do_GetService(NS_XPCOMPROXY_CONTRACTID);
printf("ProxyObjectManager: %p \n", (void *) manager.get());
PR_ASSERT(manager);
nsITestProxy *proxyObject;
nsITestProxy *proxyObject2;
nsTestXPCFoo* foo = new nsTestXPCFoo();
nsTestXPCFoo2* foo2 = new nsTestXPCFoo2();
PR_ASSERT(foo);
PR_ASSERT(foo2);
manager->GetProxyForObject(argsStruct->thread, NS_GET_IID(nsITestProxy), foo, NS_PROXY_SYNC, (void**)&proxyObject);
manager->GetProxyForObject(argsStruct->thread, NS_GET_IID(nsITestProxy), foo2, NS_PROXY_SYNC, (void**)&proxyObject2);
if (proxyObject && proxyObject2)
{
// release ownership of the real object.
PRInt32 a;
nsresult rv;
PRInt32 threadNumber = argsStruct->threadNumber;
printf("Deleting real Object (%d)\n", threadNumber);
NS_RELEASE(foo);
printf("Deleting real Object 2 (%d)\n", threadNumber);
NS_RELEASE(foo2);
printf("Thread (%d) Prior to calling proxyObject->Test.\n", threadNumber);
rv = proxyObject->Test(threadNumber, 0, &a);
printf("Thread (%d) error: %d.\n", threadNumber, rv);
printf("Thread (%d) Prior to calling proxyObject->Test2.\n", threadNumber);
rv = proxyObject->Test2();
printf("Thread (%d) error: %d.\n", threadNumber, rv);
printf("Thread (%d) Prior to calling proxyObject2->Test2.\n", threadNumber);
rv = proxyObject2->Test2();
printf("Thread (%d) proxyObject2 error: %d.\n", threadNumber, rv);
printf("Deleting Proxy Object (%d)\n", threadNumber );
NS_RELEASE(proxyObject);
printf("Deleting Proxy Object 2 (%d)\n", threadNumber );
NS_RELEASE(proxyObject2);
}
PR_Sleep( PR_MillisecondsToInterval(1000) ); // If your thread goes away, your stack goes away. Only use ASYNC on calls that do not have out parameters
}
#endif
void TestCase_NestedLoop(nsIThread *thread, PRInt32 index)
{
nsCOMPtr<nsIProxyObjectManager> manager =
do_GetService(NS_XPCOMPROXY_CONTRACTID);
LOG(("TEST: ProxyObjectManager: %p\n", (void *) manager.get()));
PR_ASSERT(manager);
nsITestProxy *proxyObject;
nsTestXPCFoo2* foo = new nsTestXPCFoo2();
PR_ASSERT(foo);
manager->GetProxyForObject(thread, NS_GET_IID(nsITestProxy), foo, NS_PROXY_SYNC, (void**)&proxyObject);
if (proxyObject)
{
// release ownership of the real object.
nsresult rv;
LOG(("TEST: Deleting real Object (%d)\n", index));
NS_RELEASE(foo);
PRInt32 retval;
LOG(("TEST: Getting EventThread...\n"));
//nsCOMPtr<nsIThread> curThread = do_GetCurrentThread();
PRThread *curThread = PR_GetCurrentThread();
if (curThread)
{
LOG(("TEST: Thread (%d) Prior to calling proxyObject->Test.\n", index));
rv = proxyObject->Test(NS_PTR_TO_INT32((void*)curThread), 0, &retval); // XXX broken on 64-bit arch
LOG(("TEST: Thread (%d) proxyObject error: %x.\n", index, rv));
LOG(("TEST: Deleting Proxy Object (%d)\n", index));
NS_RELEASE(proxyObject);
}
PR_Sleep( PR_MillisecondsToInterval(1000) ); // If your thread goes away, your stack goes away. Only use ASYNC on calls that do not have out parameters
}
}
#if 0
void TestCase_nsISupports(void *arg)
{
ArgsStruct *argsStruct = (ArgsStruct*) arg;
nsCOMPtr<nsIProxyObjectManager> manager =
do_GetService(NS_XPCOMPROXY_CONTRACTID);
PR_ASSERT(manager);
nsITestProxy *proxyObject;
nsTestXPCFoo* foo = new nsTestXPCFoo();
PR_ASSERT(foo);
manager->GetProxyForObject(argsStruct->thread, NS_GET_IID(nsITestProxy), foo, NS_PROXY_SYNC, (void**)&proxyObject);
if (proxyObject != nsnull)
{
nsISupports *bISupports = nsnull, *cISupports = nsnull;
proxyObject->Test3(foo, &bISupports);
proxyObject->Test3(bISupports, &cISupports);
nsITestProxy *test;
bISupports->QueryInterface(NS_GET_IID(nsITestProxy), (void**)&test);
test->Test2();
NS_RELEASE(foo);
NS_RELEASE(proxyObject);
}
}
#endif
/***************************************************************************/
/* ProxyTest */
/***************************************************************************/
class ProxyTest : public nsIRunnable
{
public:
NS_DECL_ISUPPORTS
ProxyTest(PRThread *eventLoopThread, PRInt32 index)
: mEventLoopThread(eventLoopThread)
, mIndex(index)
{}
NS_IMETHOD Run()
{
//TestCase_TwoClassesOneInterface(arg);
//TestCase_nsISupports(arg);
nsCOMPtr<nsIThread> thread;
GetThreadFromPRThread(mEventLoopThread, getter_AddRefs(thread));
TestCase_NestedLoop(thread, mIndex);
return NS_OK;
}
private:
PRThread *mEventLoopThread;
PRInt32 mIndex;
};
NS_IMPL_THREADSAFE_ISUPPORTS1(ProxyTest, nsIRunnable)
class TestSyncProxyToSelf : public nsIRunnable
{
public:
NS_DECL_ISUPPORTS
NS_IMETHOD Run()
{
LOG(("TEST: Verifing calling Proxy on eventQ thread.\n"));
nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
nsITestProxy *proxyObject;
nsTestXPCFoo *foo = new nsTestXPCFoo();
NS_ENSURE_STATE(foo);
nsCOMPtr<nsIProxyObjectManager> manager =
do_GetService(NS_XPCOMPROXY_CONTRACTID);
manager->GetProxyForObject(thread,
NS_GET_IID(nsITestProxy), foo,
NS_PROXY_SYNC, (void**)&proxyObject);
PRInt32 a;
proxyObject->Test(1, 2, &a);
proxyObject->Test2();
NS_RELEASE(proxyObject);
delete foo;
LOG(("TEST: End of Verification calling Proxy on eventQ thread.\n"));
return NS_OK;
}
};
NS_IMPL_THREADSAFE_ISUPPORTS1(TestSyncProxyToSelf, nsIRunnable)
//---------------------------------------------------------------------------
// Test to make sure we can call methods on a "main thread only" object from
// a background thread.
class MainThreadOnly : public nsIRunnable {
public:
NS_DECL_ISUPPORTS
NS_IMETHOD Run() {
NS_ASSERTION(NS_IsMainThread(), "method called on wrong thread");
*mNumRuns -= 1;
return NS_OK;
}
MainThreadOnly(PRUint32 *numRuns) : mNumRuns(numRuns) {}
~MainThreadOnly() {
NS_ASSERTION(NS_IsMainThread(), "method called on wrong thread");
}
PRBool IsDone() { return mNumRuns == 0; }
private:
PRUint32 *mNumRuns;
};
NS_IMPL_ISUPPORTS1(MainThreadOnly, nsIRunnable) // not threadsafe!
static nsresult
RunApartmentTest()
{
LOG(("RunApartmentTest: start\n"));
const PRUint32 numDispatched = 160;
PRUint32 numCompleted = 0;
nsCOMPtr<nsIRunnable> obj = new MainThreadOnly(&numCompleted);
nsCOMPtr<nsIProxyObjectManager> manager =
do_GetService(NS_XPCOMPROXY_CONTRACTID);
nsCOMPtr<nsIRunnable> objProxy;
manager->GetProxyForObject(NS_PROXY_TO_CURRENT_THREAD,
NS_GET_IID(nsIRunnable),
obj,
NS_PROXY_ASYNC,
getter_AddRefs(objProxy));
nsCOMPtr<nsIThread> thread;
NS_NewThread(getter_AddRefs(thread));
obj = nsnull;
nsCOMPtr<nsIThreadPool> pool = do_CreateInstance(NS_THREADPOOL_CONTRACTID);
pool->SetThreadLimit(8);
for (PRUint32 i = 0; i < numDispatched; ++i)
pool->Dispatch(objProxy, NS_DISPATCH_NORMAL);
objProxy = nsnull;
nsCOMPtr<nsIThread> curThread = do_GetCurrentThread();
while (numCompleted < numDispatched) {
NS_ProcessNextEvent(curThread);
}
pool->Shutdown();
LOG(("RunApartmentTest: end\n"));
return NS_OK;
}
} // namespace
using namespace proxytests;
int
main(int argc, char **argv)
{
int numberOfThreads = 1;
if (argc > 1)
numberOfThreads = atoi(argv[1]);
NS_InitXPCOM2(nsnull, nsnull, nsnull);
// Scope code so everything is destroyed before we run call NS_ShutdownXPCOM
{
nsCOMPtr<nsIComponentRegistrar> registrar;
NS_GetComponentRegistrar(getter_AddRefs(registrar));
registrar->AutoRegister(nsnull);
RunApartmentTest();
nsCOMPtr<nsIThread> eventLoopThread;
NS_NewThread(getter_AddRefs(eventLoopThread));
nsCOMPtr<nsIRunnable> test = new TestSyncProxyToSelf();
eventLoopThread->Dispatch(test, NS_DISPATCH_NORMAL);
PRThread *eventLoopPRThread;
eventLoopThread->GetPRThread(&eventLoopPRThread);
PR_ASSERT(eventLoopPRThread);
LOG(("TEST: Spawn Threads:\n"));
nsCOMArray<nsIThread> threads;
for (PRInt32 spawn = 0; spawn < numberOfThreads; spawn++)
{
test = new ProxyTest(eventLoopPRThread, spawn);
nsCOMPtr<nsIThread> thread;
NS_NewThread(getter_AddRefs(thread), test);
threads.AppendObject(thread);
LOG(("TEST: \tThread (%d) spawned\n", spawn));
PR_Sleep( PR_MillisecondsToInterval(250) );
}
LOG(("TEST: All Threads Spawned.\n"));
LOG(("TEST: Wait for threads.\n"));
for (PRInt32 i = 0; i < numberOfThreads; i++)
{
LOG(("TEST: Thread (%d) Join...\n", i));
nsresult rv = threads[i]->Shutdown();
LOG(("TEST: Thread (%d) Joined. (error: %x).\n", i, rv));
}
LOG(("TEST: Shutting down event loop thread\n"));
eventLoopThread->Shutdown();
}
LOG(("TEST: Calling Cleanup.\n"));
NS_ShutdownXPCOM(nsnull);
LOG(("TEST: Return zero.\n"));
return 0;
}

View File

@@ -1,33 +0,0 @@
namespace Parser
{
namespace XXX
{
class Foobar
{
class Blah
{
class Bar
{
class Lalala
{
public:
Foobar();
}
}
}
};
};
};
void*
Parser::XXX::Foobar::wait(int i, const char const * const * p)
{
return;
}
void
Foobar::non_nil()
{
return;
}

View File

@@ -1,12 +0,0 @@
int animal::moose::getFeet() //^2^
{
return fFeet;
}
void animal::moose::doNothing() //^3^
{
animal::moose foo();
fFeet = N// -15-
; // #15# ( "NAME1" "NAME2" "NAME3" )
}

View File

@@ -1,157 +0,0 @@
// ICoder.h
using System;
namespace SevenZip
{
/// <summary>
/// The exception that is thrown when an error in input stream occurs during decoding.
/// </summary>
class DataErrorException : ApplicationException
{
public DataErrorException(): base("Data Error") { }
}
/// <summary>
/// The exception that is thrown when the value of an argument is outside the allowable range.
/// </summary>
class InvalidParamException : ApplicationException
{
public InvalidParamException(): base("Invalid Parameter") { }
}
public interface ICodeProgress
{
/// <summary>
/// Callback progress.
/// </summary>
/// <param name="inSize">
/// input size. -1 if unknown.
/// </param>
/// <param name="outSize">
/// output size. -1 if unknown.
/// </param>
void SetProgress(Int64 inSize, Int64 outSize);
};
public interface ICoder
{
/// <summary>
/// Codes streams.
/// </summary>
/// <param name="inStream">
/// input Stream.
/// </param>
/// <param name="outStream">
/// output Stream.
/// </param>
/// <param name="inSize">
/// input Size. -1 if unknown.
/// </param>
/// <param name="outSize">
/// output Size. -1 if unknown.
/// </param>
/// <param name="progress">
/// callback progress reference.
/// </param>
/// <exception cref="SevenZip.DataErrorException">
/// if input stream is not valid
/// </exception>
void Code(System.IO.Stream inStream, System.IO.Stream outStream,
Int64 inSize, Int64 outSize, ICodeProgress progress);
};
/*
public interface ICoder2
{
void Code(ISequentialInStream []inStreams,
const UInt64 []inSizes,
ISequentialOutStream []outStreams,
UInt64 []outSizes,
ICodeProgress progress);
};
*/
/// <summary>
/// Provides the fields that represent properties idenitifiers for compressing.
/// </summary>
public enum CoderPropID
{
/// <summary>
/// Specifies default property.
/// </summary>
DefaultProp = 0,
/// <summary>
/// Specifies size of dictionary.
/// </summary>
DictionarySize,
/// <summary>
/// Specifies size of memory for PPM*.
/// </summary>
UsedMemorySize,
/// <summary>
/// Specifies order for PPM methods.
/// </summary>
Order,
/// <summary>
/// Specifies Block Size.
/// </summary>
BlockSize,
/// <summary>
/// Specifies number of postion state bits for LZMA (0 <= x <= 4).
/// </summary>
PosStateBits,
/// <summary>
/// Specifies number of literal context bits for LZMA (0 <= x <= 8).
/// </summary>
LitContextBits,
/// <summary>
/// Specifies number of literal position bits for LZMA (0 <= x <= 4).
/// </summary>
LitPosBits,
/// <summary>
/// Specifies number of fast bytes for LZ*.
/// </summary>
NumFastBytes,
/// <summary>
/// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B".
/// </summary>
MatchFinder,
/// <summary>
/// Specifies the number of match finder cyckes.
/// </summary>
MatchFinderCycles,
/// <summary>
/// Specifies number of passes.
/// </summary>
NumPasses,
/// <summary>
/// Specifies number of algorithm.
/// </summary>
Algorithm,
/// <summary>
/// Specifies the number of threads.
/// </summary>
NumThreads,
/// <summary>
/// Specifies mode with end marker.
/// </summary>
EndMarker
};
public interface ISetCoderProperties
{
void SetCoderProperties(CoderPropID[] propIDs, object[] properties);
};
public interface IWriteCoderProperties
{
void WriteCoderProperties(System.IO.Stream outStream);
}
public interface ISetDecoderProperties
{
void SetDecoderProperties(byte[] properties);
}
}

View File

@@ -1,234 +0,0 @@
using System;
namespace SevenZip.Compression.RangeCoder
{
class Encoder
{
public const uint kTopValue = (1 << 24);
System.IO.Stream Stream;
public UInt64 Low;
public uint Range;
uint _cacheSize;
byte _cache;
long StartPosition;
public void SetStream(System.IO.Stream stream)
{
Stream = stream;
}
public void ReleaseStream()
{
Stream = null;
}
public void Init()
{
StartPosition = Stream.Position;
Low = 0;
Range = 0xFFFFFFFF;
_cacheSize = 1;
_cache = 0;
}
public void FlushData()
{
for (int i = 0; i < 5; i++)
ShiftLow();
}
public void FlushStream()
{
Stream.Flush();
}
public void CloseStream()
{
Stream.Close();
}
public void Encode(uint start, uint size, uint total)
{
Low += start * (Range /= total);
Range *= size;
while (Range < kTopValue)
{
Range <<= 8;
ShiftLow();
}
}
public void ShiftLow()
{
if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1)
{
byte temp = _cache;
do
{
Stream.WriteByte((byte)(temp + (Low >> 32)));
temp = 0xFF;
}
while (--_cacheSize != 0);
_cache = (byte)(((uint)Low) >> 24);
}
_cacheSize++;
Low = ((uint)Low) << 8;
}
public void EncodeDirectBits(uint v, int numTotalBits)
{
for (int i = numTotalBits - 1; i >= 0; i--)
{
Range >>= 1;
if (((v >> i) & 1) == 1)
Low += Range;
if (Range < kTopValue)
{
Range <<= 8;
ShiftLow();
}
}
}
public void EncodeBit(uint size0, int numTotalBits, uint symbol)
{
uint newBound = (Range >> numTotalBits) * size0;
if (symbol == 0)
Range = newBound;
else
{
Low += newBound;
Range -= newBound;
}
while (Range < kTopValue)
{
Range <<= 8;
ShiftLow();
}
}
public long GetProcessedSizeAdd()
{
return _cacheSize +
Stream.Position - StartPosition + 4;
// (long)Stream.GetProcessedSize();
}
}
class Decoder
{
public const uint kTopValue = (1 << 24);
public uint Range;
public uint Code;
// public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16);
public System.IO.Stream Stream;
public void Init(System.IO.Stream stream)
{
// Stream.Init(stream);
Stream = stream;
Code = 0;
Range = 0xFFFFFFFF;
for (int i = 0; i < 5; i++)
Code = (Code << 8) | (byte)Stream.ReadByte();
}
public void ReleaseStream()
{
// Stream.ReleaseStream();
Stream = null;
}
public void CloseStream()
{
Stream.Close();
}
public void Normalize()
{
while (Range < kTopValue)
{
Code = (Code << 8) | (byte)Stream.ReadByte();
Range <<= 8;
}
}
public void Normalize2()
{
if (Range < kTopValue)
{
Code = (Code << 8) | (byte)Stream.ReadByte();
Range <<= 8;
}
}
public uint GetThreshold(uint total)
{
return Code / (Range /= total);
}
public void Decode(uint start, uint size, uint total)
{
Code -= start * Range;
Range *= size;
Normalize();
}
public uint DecodeDirectBits(int numTotalBits)
{
uint range = Range;
uint code = Code;
uint result = 0;
for (int i = numTotalBits; i > 0; i--)
{
range >>= 1;
/*
result <<= 1;
if (code >= range)
{
code -= range;
result |= 1;
}
*/
uint t = (code - range) >> 31;
code -= range & (t - 1);
result = (result << 1) | (1 - t);
if (range < kTopValue)
{
code = (code << 8) | (byte)Stream.ReadByte();
range <<= 8;
}
}
Range = range;
Code = code;
return result;
}
public uint DecodeBit(uint size0, int numTotalBits)
{
uint newBound = (Range >> numTotalBits) * size0;
uint symbol;
if (Code < newBound)
{
symbol = 0;
Range = newBound;
}
else
{
symbol = 1;
Code -= newBound;
Range -= newBound;
}
Normalize();
return symbol;
}
// ulong GetProcessedSize() {return Stream.GetProcessedSize(); }
}
}

View File

@@ -1,157 +0,0 @@
using System;
namespace SevenZip.Compression.RangeCoder
{
struct BitTreeEncoder
{
BitEncoder[] Models;
int NumBitLevels;
public BitTreeEncoder(int numBitLevels)
{
NumBitLevels = numBitLevels;
Models = new BitEncoder[1 << numBitLevels];
}
public void Init()
{
for (uint i = 1; i < (1 << NumBitLevels); i++)
Models[i].Init();
}
public void Encode(Encoder rangeEncoder, UInt32 symbol)
{
UInt32 m = 1;
for (int bitIndex = NumBitLevels; bitIndex > 0; )
{
bitIndex--;
UInt32 bit = (symbol >> bitIndex) & 1;
Models[m].Encode(rangeEncoder, bit);
m = (m << 1) | bit;
}
}
public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol)
{
UInt32 m = 1;
for (UInt32 i = 0; i < NumBitLevels; i++)
{
UInt32 bit = symbol & 1;
Models[m].Encode(rangeEncoder, bit);
m = (m << 1) | bit;
symbol >>= 1;
}
}
public UInt32 GetPrice(UInt32 symbol)
{
UInt32 price = 0;
UInt32 m = 1;
for (int bitIndex = NumBitLevels; bitIndex > 0; )
{
bitIndex--;
UInt32 bit = (symbol >> bitIndex) & 1;
price += Models[m].GetPrice(bit);
m = (m << 1) + bit;
}
return price;
}
public UInt32 ReverseGetPrice(UInt32 symbol)
{
UInt32 price = 0;
UInt32 m = 1;
for (int i = NumBitLevels; i > 0; i--)
{
UInt32 bit = symbol & 1;
symbol >>= 1;
price += Models[m].GetPrice(bit);
m = (m << 1) | bit;
}
return price;
}
public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex,
int NumBitLevels, UInt32 symbol)
{
UInt32 price = 0;
UInt32 m = 1;
for (int i = NumBitLevels; i > 0; i--)
{
UInt32 bit = symbol & 1;
symbol >>= 1;
price += Models[startIndex + m].GetPrice(bit);
m = (m << 1) | bit;
}
return price;
}
public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex,
Encoder rangeEncoder, int NumBitLevels, UInt32 symbol)
{
UInt32 m = 1;
for (int i = 0; i < NumBitLevels; i++)
{
UInt32 bit = symbol & 1;
Models[startIndex + m].Encode(rangeEncoder, bit);
m = (m << 1) | bit;
symbol >>= 1;
}
}
}
struct BitTreeDecoder
{
BitDecoder[] Models;
int NumBitLevels;
public BitTreeDecoder(int numBitLevels)
{
NumBitLevels = numBitLevels;
Models = new BitDecoder[1 << numBitLevels];
}
public void Init()
{
for (uint i = 1; i < (1 << NumBitLevels); i++)
Models[i].Init();
}
public uint Decode(RangeCoder.Decoder rangeDecoder)
{
uint m = 1;
for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--)
m = (m << 1) + Models[m].Decode(rangeDecoder);
return m - ((uint)1 << NumBitLevels);
}
public uint ReverseDecode(RangeCoder.Decoder rangeDecoder)
{
uint m = 1;
uint symbol = 0;
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
{
uint bit = Models[m].Decode(rangeDecoder);
m <<= 1;
m += bit;
symbol |= (bit << bitIndex);
}
return symbol;
}
public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex,
RangeCoder.Decoder rangeDecoder, int NumBitLevels)
{
uint m = 1;
uint symbol = 0;
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
{
uint bit = Models[startIndex + m].Decode(rangeDecoder);
m <<= 1;
m += bit;
symbol |= (bit << bitIndex);
}
return symbol;
}
}
}

View File

@@ -1,64 +0,0 @@
class
POINT
inherit
ANY
redefine
out
end
create
make, make_origin
feature -- Initialization
make (a_x, a_y: INTEGER)
-- Create with values `a_x' and `a_y'
do
set_x (a_x)
set_y (a_y)
ensure
x_set: x = a_x
y_set: y = a_y
end
make_origin
-- Create at origin
do
ensure
x_set: x = 0
y_set: y = 0
end
feature -- Access
x: INTEGER assign set_x
-- Horizontal axis coordinate
y: INTEGER assign set_y
-- Vertical axis coordinate
feature -- Element change
set_x (a_x: INTEGER)
-- Set `x' coordinate to `a_x'
do
x := a_x
ensure
x_set: x = a_x
end
set_y (a_y: INTEGER)
-- Set `y' coordinate to `a_y'
do
y := a_y
ensure
y_set: y = a_y
end
feature -- Output
out: STRING
-- Display as string
do
Result := "Point: x = " + x.out + " y = " + y.out
end
end

View File

@@ -1,34 +0,0 @@
COMPILER ebnf.
CHARACTERS
small = "abcdefghijklmnopqrstuvwxyz";
big = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
alpha = small + big;
dig = "0123456789";
blank = CHR(9) + CHR(10) + CHR(32);
noQuote = ANY - '"'.
COMMENTS
FROM "(*" TO "*)" NESTED.
TOKENS
Nonterminal = small {alpha | dig};
Terminal = big {alpha | dig};
White = blank {blank};
String = '"' { noQuote } '"'.
IGNORE
White + Comment.
PRODUCTIONS
ebnf = {production} ".";
production = Nonterminal "=" expr ";" ;
expr = term {"|" term};
term = factor {factor};
factor = "{" expr "}"
| "[" expr "]"
| "(" expr ")"
| Nonterminal | Terminal | String.
END ebnf.

View File

@@ -1,117 +0,0 @@
Definitions.
Dig = [0-9]
Big = [A-Z]
Small = [a-z]
WS = [\000-\s]
COMMENT = \(\*\(*([^*)]|[^*]\)|\*[^)])*\**\*\)
STRING = "(\\\^.|\\.|[^"])*"
QUOTE = '(\\\^.|\\.|[^'])*'
Rules.
({Small}({Small}|{Big}|{Dig}|_)*) : {token, {atom,YYline, YYtext}}.
({Big}({Small}|{Big}|{Dig}|_)*) : {token, special(YYtext, YYline)}.
({Dig}{Dig}*) : {token, {integer, YYline, list_to_integer(YYtext)}}.
%% string
{STRING} : %% Strip quotes.
S = lists:sublist(YYtext, 2, length(YYtext) - 2),
{token,{string,YYline,string_gen(S)}}.
{QUOTE} : %% Strip quotes.
S = lists:sublist(YYtext, 2, length(YYtext) - 2),
{token,{quote,YYline,string_gen(S)}}.
{COMMENT} : .
%%---------------------------------------------------------
%% Ignore stuff
%%---------------------------------------------------------
%% "{WHITE}". %% whitespace
%% "#.*". %% Ignore Macro stuff for now
%% "{COMMENT}". %% Ignore Comments
%% C comments are /* ... */
%% Our comments are (* ... *) {we have to quote ( and * yuck
%% i.e. write \* and \( }
%%
%% COMMENT "/\\*/*([^*/]|[^*]/|\\*[^/])*\\**\\*/". (tobbe)
%% COMMENT "(\\*/*([^*)]|[^*])|\\*[^)])*\\**\\*)". (modified)
%% COMMENT "\(\\*/*([^*\)]|[^*]\)|\\*[^\)])*\\**\\*\)". (quoted)
= : {token, {'=', YYline}}.
\+ : {token, {'+', YYline}}.
\- : {token, {'-', YYline}}.
\; : {token, {';', YYline}}.
} : {token, {'}', YYline}}.
{ : {token, {'{', YYline}}.
\[ : {token, {'[', YYline}}.
\] : {token, {']', YYline}}.
\( : {token, {'(', YYline}}.
\) : {token, {')', YYline}}.
\| : {token, {'|', YYline}}.
\: : {token, {':', YYline}}.
(.|\n) : skip_token.
\.[\s\t\n] : {end_token,{'$end', YYline}}.
Erlang code.
string_gen([$\\|Cs]) ->
string_escape(Cs);
string_gen([C|Cs]) ->
[C|string_gen(Cs)];
string_gen([]) -> [].
string_escape([O1,O2,O3|S]) when
O1 >= $0, O1 =< $7, O2 >= $0, O2 =< $7, O3 >= $0, O3 =< $7 ->
[(O1*8 + O2)*8 + O3 - 73*$0|string_gen(S)];
string_escape([$^,C|Cs]) ->
[C band 31|string_gen(Cs)];
string_escape([C|Cs]) when C >= 0, C =< $ ->
string_gen(Cs);
string_escape([C|Cs]) ->
[escape_char(C)|string_gen(Cs)].
escape_char($n) -> $\n; %\n = LF
escape_char($r) -> $\r; %\r = CR
escape_char($t) -> $\t; %\t = TAB
escape_char($v) -> $\v; %\v = VT
escape_char($b) -> $\b; %\b = BS
escape_char($f) -> $\f; %\f = FF
escape_char($e) -> $\e; %\e = ESC
escape_char($s) -> $ ; %\s = SPC
escape_char($d) -> $\d; %\d = DEL
escape_char(C) -> C.
remove_brackets([_,_|T]) ->
[_,_|T1] = lists:reverse(T),
lists:reverse(T1).
special("COMPILER", Line) -> {'COMPILER', Line};
special("CHARACTERS", Line) -> {'CHARACTERS', Line};
special("COMMENTS", Line) -> {'COMMENTS', Line};
special("FROM", Line) -> {'FROM', Line};
special("TO", Line) -> {'TO', Line};
special("TOKENS", Line) -> {'TOKENS', Line};
special("IGNORE", Line) -> {'IGNORE', Line};
special("PRODUCTIONS", Line) -> {'PRODUCTIONS', Line};
special("END", Line) -> {'END', Line};
special("NESTED", Line) -> {'NESTED', Line};
special("EOL", Line) -> {'EOL', Line};
special("CHR", Line) -> {'CHR', Line};
special("ANY", Line) -> {'ANY', Line};
special(Other, Line) -> {var, Line, Other}.

View File

@@ -1,105 +0,0 @@
Nonterminals
production
form lhs factor
nested syntax char_prods charline char_rhs char_prim
ignore moreignore expr term.
Terminals
atom var string quote '|' '=' '}' '{' '(' ')' '[' ']'
'COMPILER' 'CHARACTERS' 'COMMENTS' 'FROM' 'TO' 'TOKENS'
'IGNORE' 'PRODUCTIONS' 'END' 'NESTED' 'EOL' 'CHR' 'ANY' integer comment
'+' '-' ';'.
Rootsymbol form.
form -> 'COMPILER' atom : {compiler, unwrap('$2')}.
form -> 'CHARACTERS' char_prods : {characters, '$2'}.
form -> 'COMMENTS' 'FROM' string
'TO' string nested : {comments,unwrap('$3'),unwrap('$5'),
'$6'}.
form -> 'TOKENS' syntax : {tokens, '$2'}.
form -> 'IGNORE' ignore : {ignore, '$2'}.
form -> 'PRODUCTIONS' syntax : {syntax, '$2'}.
form -> 'END' atom : {theend, '$2'}.
form -> comment.
nested -> 'NESTED' : nested.
nested -> 'EOL' : eol.
nested -> '$empty' : not_nested.
%% Character syntax
char_prods -> charline ';' char_prods : ['$1'|'$3'].
char_prods -> charline : ['$1'].
charline -> atom '=' char_rhs : {unwrap('$1'), '$3'}.
char_rhs -> char_prim '+' char_rhs : {plus, '$1', '$3'}.
char_rhs -> char_prim '-' char_rhs : {minus, '$1', '$3'}.
char_rhs -> char_prim : '$1'.
char_prim -> 'CHR' '(' integer ')' : {chr, unwrap('$3')}.
char_prim -> string : {string, unwrap('$1')}.
char_prim -> quote : {string, unwrap('$1')}.
char_prim -> atom : {atom, unwrap('$1')}.
char_prim -> 'ANY' : any.
ignore -> var moreignore : [unwrap('$1')|'$2'].
moreignore -> '+' ignore : '$2'.
moreignore -> '$empty' : [].
%% The following deifinitions are taken from [WIR82]
%% WIR82 Programming in Modular2
%% Springer Verlag 1982
%% statement : A syntactic form
%% expression : A list of alternatives
%% term : A concatination of factors
%% factor : A single syntactoc entity or a parenthesized expression
%% Construct
%% =========
%% [ A ] = zero or more A's
%% { A } = any number of A's
%% "A" = a string parse tree
%% A | B = A or B parse tree
%% A B = sequence of A followed by B
%% identifier = a name
%% syntax = {production}
%% production = id "=" expr ";"
%% expr = term {"|" term}
%% term = factor {factor}
%% factor = id | string "{" expr "}
syntax -> production ';' syntax : ['$1'|'$3'].
syntax -> production : ['$1'].
production -> lhs '=' expr : {prod, '$1', '$3'}.
lhs -> var : unwrap('$1').
lhs -> atom : unwrap('$1').
expr -> term : '$1'.
expr -> term '|' expr : {alt, '$1', '$3'}.
term -> factor : '$1'.
term -> factor term : {seq, '$1', '$2'}.
factor -> atom : {nt, unwrap('$1')}.
factor -> var : {ta, unwrap('$1')}.
factor -> string : {ts, unwrap('$1')}.
factor -> quote : {tq, unwrap('$1')}.
factor -> '[' expr ']' : {one, '$2'}.
factor -> '{' expr '}' : {star, '$2'}.
factor -> '(' expr ')' : {bracket, '$2'}.
Erlang code.
unwrap({_,_,V}) -> V.
simplify({Tag,A,nil}) -> A;
simplify(X) -> X.

View File

@@ -1,58 +0,0 @@
-module(ecc_parse).
-doc([{author, 'Joe Armstrong'},
{title, "Parser for the <b>ecc</b> language."},
{keywords,[ecc,parser,yecc,leex]},
{date, 891106}]).
-export([make/0, file/1]).
%% usage
%% ecc_parse:file(File)
%% Converts File.ebnf -> File.xbin
%% ecc_parse:make()
%% Makes the parser
make() ->
%% The parser is made from
%% ecc.yrl and ecc.xrl
yecc:yecc("ecc", "ecc_yecc"),
c:c(ecc_yecc),
leex:gen(ecc, ecc_lex),
c:c(ecc_lex).
file(F) ->
io:format("Parsing ~s.ecc~n", [F]),
{ok, Stream} = file:open(F ++ ".ecc", read),
Parse = handle(Stream, 1, [], 0),
file:close(Stream),
Parse.
handle(Stream, LineNo, L, NErrors) ->
handle1(io:requests(Stream, [{get_until,foo,ecc_lex,
tokens,[LineNo]}]), Stream, L, NErrors).
handle1({ok, Toks, Next}, Stream, L, Nerrs) ->
case ecc_yecc:parse(Toks) of
{ok, Parse} ->
handle(Stream, Next, [Parse|L], Nerrs);
{error, {Line, Mod, What}} ->
Str = apply(Mod, format_error, [What]),
io:format("** ~w ~s~n", [Line, Str]),
handle(Stream, Next, L, Nerrs+1);
Other ->
io:format("Bad_parse:~p\n", [Other]),
handle(Stream, Next, L, Nerrs+1)
end;
handle1({eof, _}, Stream, L, 0) ->
{ok, lists:reverse(L)};
handle1({eof, _}, Stream, L, N) ->
{error, N};
handle1(What, Stream, L, Nerrs) ->
io:format("Here:~p\n", [What]),
handle(Stream, 1, L, Nerrs+1).
first([H]) -> [];
first([H|T]) -> [H|first(T)];
first([]) -> [].

View File

@@ -1,236 +0,0 @@
-module(ermake).
-doc([{author,'Joe Armstrong'},
{title,"Erlang make utility."},
{keywords, [make]},
{date,981103}]).
-export([all/0, target/1, file/1, file/2]).
-import(lists, [delete/2, filter/2, foldl/3, map/2, max/1, member/2, zf/2]).
%% all() -> Makes first target in EMakefile
%% target(target::string()) -> Makes Target in EMakefile
%% file(file()) -> Makes first target in File
%% file(file(), target::string()) -> Makes Target in File
all() -> file("EMakefile").
target(T) -> file("EMakefile", T).
file(File) -> make(File, top).
file(File, Target) -> make(File, {target, Target}).
make(File, Target) ->
Lines = ermake_parse:parse(File),
Rules = filter(fun(X) -> element(1, X) == make end, Lines),
Suffix = filter(fun(X) -> element(1, X) == suffix end, Lines),
Rules1 = add_extra_rules(Rules, Suffix),
case Target of
top ->
case hd(Rules) of
{make, Ts, _, _} ->
make_everything(Ts, Rules1);
_ ->
nothing_to_do
end;
{target, T} ->
make_everything([T], Rules1)
end.
add_extra_rules(Rules, Suffix) ->
%% If a dependent is mentioned and
%% there is no explicit rule for how to make the dependent then
%% add an extra rule if possible
Targets = [T || {make,Ts,_,_} <- Rules, T <- Ts],
Dependents = [D || {make, _, Ds, _} <- Rules, D <- Ds],
Missing = filter(fun(I) -> not member(I, Targets) end, Dependents),
Missing1 = remove_duplicates(Missing),
Extra = zf(fun(I) -> find_suffix_rule(I, Suffix) end, Missing1),
Rules ++ Extra.
make_everything(Targets, Rules) ->
Ps = [{T, D} || {make, Ts, Ds, _} <- Rules, T <- Ts, D <- Ds],
%% trace all the rules we can reach from the root set
L0 = transitive:closure(Targets, Ps),
L = delete(true, L0),
%% keep those rules that are mentioned in targets or destinations
Ps1 = filter(fun({D,T}) ->
member(D, L) or member(T, L)
end, Ps),
%% reverse the order to build the bottom up tree
Ps2 = map(fun({I,J}) -> {J, I} end, Ps1),
%% order the result
case topological_sort:sort(Ps2) of
{ok, Order0} ->
Order = delete(true, Order0),
%% Order is the absolute order to build things
Cmds = map(fun(I) -> select_rule(I, Rules) end, Order),
foldl(fun do_cmd/2, [], Cmds),
true;
{cycle, Cycle} ->
exit({makefile,contains,cycle,Cycle})
end.
%% find which rule is needed to build Target
select_rule(Target, Rules) ->
Matches = [{make, Ts,Ds,Fun}|| {make,Ts,Ds,Fun} <- Rules,
member(Target, Ts)],
case length(Matches) of
0 -> {file, Target};
1 -> hd(Matches);
_ -> exit({multiple,rules,to,make,Target})
end.
%% do_cmd(cmd(), made()) -> make()'
%% cmd() = {make, Targets, Dependents, Fun} | {file, Target}
%% made() = [Target, time()].
do_cmd({make, Bins, Srcs, Fun}, Made) ->
case target_time(Bins, Made) of
none ->
eval(Bins, Fun);
{missing, M} ->
eval(Bins, Fun);
{max, TBin} ->
case target_time(Srcs, Made) of
{missing, M} ->
exit({'I don\'t know how to make',M});
{max, TSrc} when TSrc > TBin ->
eval(Bins, Fun);
{max, _} ->
true;
none ->
exit({no,src,Srcs})
end
end,
update_times(Srcs ++ Bins, this_time(), Made);
do_cmd({file,H}, Made) ->
update_times([H], this_time(), Made).
%% target_time(Targets, Made) -> {max, Time} | {missing,M}
%% none
%% if no targets found
%% {missing, M}
%% if target M is missing
%% {max, Time}
%% Time is the last modified time of all the targets
%% the limes are derived from either the Made list
%% or from the time stamp of the file.
target_time(Targets, Made) ->
target_time(Targets, Made, []).
target_time([H|T], Made, Times) ->
case make_time(H, Made) of
{yes, Time} ->
target_time(T, Made, [Time|Times]);
no ->
case is_file(H) of
true ->
target_time(T, Made, [last_modified(H)|Times]);
false ->
{missing, H}
end
end;
target_time([], Made, []) ->
none;
target_time([], Made, Times) ->
{max, max(Times)}.
make_time(X, [{X,Time}|_]) -> {yes, Time};
make_time(X, [_|T]) -> make_time(X, T);
make_time(X, []) -> no.
update_times([H|T], Now, Made) ->
case make_time(H, Made) of
{yes, _} -> update_times(T, Now, Made);
no ->
case is_file(H) of
true ->
update_times(T, Now, [{H, last_modified(H)}|Made]);
false ->
update_times(T, Now, [{H, Now}|Made])
end
end;
update_times([], _, Made) ->
Made.
%% see if a suffix rule can be applied to the file D
find_suffix_rule(D, Suffix) ->
Ext = filename:extension(D),
find_suffix_rule(Ext, D, Suffix).
find_suffix_rule(To, D, [{suffix, [From, To], Fun}|_]) ->
Root = filename:rootname(D),
Fun1 = expand_cmd(Fun, Root),
{true, {make, [D], [Root ++ From], Fun1}};
find_suffix_rule(To, D, [_|T]) ->
find_suffix_rule(To, D, T);
find_suffix_rule(_, _, []) ->
false.
expand_cmd([$$,$>|T], Root) ->
Root ++ expand_cmd(T, Root);
expand_cmd([H|T], Root) ->
[H|expand_cmd(T, Root)];
expand_cmd([], _) ->
[].
eval(_, []) ->
true;
eval(Target, Str) ->
io:format("make ~p ->~n~s~n",[Target, Str]),
case erl_scan:tokens([], "fun() -> " ++ Str ++ " end. ", 1) of
{done, {ok, Toks, _},_} ->
case erl_parse:parse_exprs(Toks) of
{ok, [Parse]} ->
%% io:format("Parse = ~p~n",[Parse]),
Env0 = erl_eval:new_bindings(),
Call = [{call,9999,Parse,[]}],
case erl_eval:exprs(Call, Env0) of
{value, Val, _} ->
Val;
O3 ->
exit({eval,error,O3})
end;
O1 ->
exit({parse,error,o1,O1})
end;
O2 ->
exit({tokenisation,error,O2})
end.
%% Stuff that should have been in the libraries (sigh :-)
last_modified(F) ->
case file:file_info(F) of
{ok, {_, _, _, _, Time, _, _}} ->
Time;
_ ->
exit({last_modified, F})
end.
is_file(File) ->
case file:file_info(File) of
{ok, _} ->
true;
_ ->
false
end.
remove_duplicates(L) ->
foldl(fun(I, Acc) ->
case member(I, Acc) of
true -> Acc;
false -> [I|Acc]
end
end, [], L).
this_time() ->
{Y,M,D} = date(),
{H,Min,S} = time(),
{Y,M,D,H,Min,S}.

View File

@@ -1,246 +0,0 @@
-module(ermake_line_reader).
-doc([{author,'Joe Armstrong'},
{title,"Provide character level input for utilities such as make, lex, yacc etc. This module reads lines up to dot whitespace. Include files and named macros are expanded in place."},
{keywords, [read,line,make,dot,whitespace,forms]},
{date,981028}]).
%% This module provides a common *character level input*
%% For Erlang look-alike utilities such as make, yecc, lex
%% It provides
%% 1) Multiple line input terminated by dot white space
%% 2) Variables VAR = Val, or VAR += Val
%% 3) Include files include("File")
%% 4) comment stripping %... are removed
-export([test/1, read_file/1, read_file/2]).
-import(lists, [keyreplace/4, keysearch/3, member/2, reverse/1, reverse/2]).
test(1) -> read_file("EMakefile");
test(2) -> read_file("test1").
read_file(File) ->
read_file(File, []).
read_file(File, Macros) ->
{Macros1, Lines} = read_lines(File, Macros, [File]),
%% io:format("Macros were:~p~n",[Macros1]),
trim(Lines).
trim([{{File,Line},Str}|T]) ->
Leading = count_leading_nls(Str, Line),
case trim_line(Str) of
[] -> trim(T);
Str1 -> [{File,Leading,Str1}|trim(T)]
end;
trim([]) -> [].
trim_line(Str) ->
Str1 = skip_white(Str),
trim_end_of_line(Str1).
trim_end_of_line(Str1) ->
case reverse(Str1) of
[X,$.|Tmp] ->
reverse(Tmp);
[] ->
[];
Other ->
exit({oops,Other})
end.
read_lines(File, Macros0, Stack) ->
case file:read_file(File) of
{ok, Bin} ->
Lines = gather_lines(binary_to_list(Bin), File, 1, []),
%% io:format("Lines=~p~n",[Lines]),
expand(Lines, Macros0, Stack, []);
_ ->
exit({cannot,read,file,File})
end.
expand([{Where, H}|T], Macros, Stack, L) ->
%% first expand any macros
H1 = expand_macro(H, Macros, Where),
%% now add any macro definitions
case is_macro_defn(H1) of
{new, Var, Val} ->
case keysearch(Var,1,Macros) of
{value,{_,Val}} ->
%% same value no problem
expand(T, Macros, Stack, L);
{value,{_,Replacement}} ->
%% some other value
exit({error, Where, cannot,redefine,macro,
Var,was,Replacement,is,Val});
false ->
%% new definition
expand(T, [{Var,Val}|Macros], Stack, L)
end;
{plus, Var, Val} ->
case keysearch(Var,1,Macros) of
{value,{_,Old}} ->
%% some other value
Macros1 = keyreplace(Var,1,Macros,{Var,Old++Val}),
expand(T, Macros1, Stack, L);
false ->
exit({error, Where, no,previous,defn,for,Var})
end;
no ->
case is_include(H1, Where) of
{yes, File} ->
case member(File, Stack) of
true ->
exit({error, Where, recursive_include, File});
false ->
{Macros1, Lines1} = read_lines(File,Macros,Stack),
expand(T, Macros1, Stack, reverse(Lines1, L))
end;
no ->
expand(T, Macros, Stack, [{Where, H1}|L])
end
end;
expand([], Macros, Stack, L) ->
{Macros, reverse(L)}.
expand_macro([$$,$(|T], Macros, Where) ->
case is_var(T) of
{yes, Var, [$)|T1]} ->
case keysearch(Var,1,Macros) of
{value,{_,Replacement}} ->
Replacement ++ expand_macro(T1, Macros, Where);
false ->
exit({error,Where,undefined,macro,Var})
end;
no ->
[$$,$(|expand_macro(T, Macros, Where)]
end;
expand_macro([H|T], Macros, Where) ->
[H|expand_macro(T, Macros, Where)];
expand_macro([], Macros, _) ->
[].
is_include(Line, Where) ->
case skip_white(Line) of
[$i,$n,$c,$l,$u,$d,$e,$(,$"|T] ->
{File, T1} = get_quoted([$"|T], Where),
case skip_white(T1) of
[$)|_] ->
{yes, File};
_ ->
exit({Where,bad,include,syntax})
end;
_ ->
no
end.
is_macro_defn(Line) ->
Str1 = skip_white(Line),
case is_var(Str1) of
{yes, Var, Str2} ->
case skip_white(Str2) of
[$=|T] ->
{new, Var, trim_end_of_line(T)};
[$+,$=|T] ->
{plus, Var, trim_end_of_line(T)};
_ ->
no
end;
no ->
no
end.
is_var([H|T]) when $A =< H, H =< $Z ->
collect_var(T, [H]);
is_var(_) ->
no.
collect_var([H|T], L) when $A =< H, H =< $Z ->
collect_var(T, [H|L]);
collect_var([H|T], L) when $1 =< H, H =< $9 ->
collect_var(T, [H|L]);
collect_var([H|T], L) when $a =< H, H =< $z ->
collect_var(T, [H|L]);
collect_var(X, L) ->
{yes, reverse(L), X}.
skip_white([$ |T]) -> skip_white(T);
skip_white([$\n|T]) -> skip_white(T);
skip_white([$\t|T]) -> skip_white(T);
skip_white(T) -> T.
gather_lines([], File, N, L) ->
reverse(L);
gather_lines(Str, File, N, L) ->
{Line, Str1} = get_line(Str, {File, N}, []),
Width = count_nls(Line, 0),
gather_lines(Str1, File, N + Width, [{{File,N},Line}|L]).
count_nls([$\n|T], N) -> count_nls(T, N+1);
count_nls([_|T], N) -> count_nls(T, N);
count_nls([], N) -> N.
count_leading_nls([$\n|T], N) -> count_leading_nls(T, N+1);
count_leading_nls(_, N) -> N.
%% get_line collects a line up to . <white>
get_line([$.,X|T], Where, L) ->
case X of
$\n ->
{reverse(L, [$.,$\n]), T};
$ ->
{reverse(L, [". "]), T};
$\t ->
{reverse(L, [$.,$\t]), T};
_ ->
get_line(T, Where, [X,$.|L])
end;
get_line([$"|T], Where, L) ->
{Str, T1} = get_quoted([$"|T], Where),
get_line(T1, Where, [$"|reverse(Str, [$"|L])]);
get_line([$'|T], Where, L) ->
{Str, T1} = get_quoted([$'|T], Where),
get_line(T1, Where,[$'|reverse(Str, [$'|L])]);
get_line([$%|T], Where, L) ->
%% remove the comment
T1 = skip_to_eol(T),
get_line(T1, Where, L);
get_line([H|T], Where, L) ->
get_line(T, Where, [H|L]);
get_line([], Where, L) ->
{reverse(L), []}.
skip_to_eol([$\n|T]) -> [$\n|T];
skip_to_eol([_|T]) -> skip_to_eol(T);
skip_to_eol([]) -> [].
%% get_quoted(string(), {file(),line()}) -> {quoted(), rest()}
%% The " ' is not included
get_quoted([End|T], Where) ->
get_quoted(T, Where, End, []).
get_quoted([End|T], Where, End, Acc) ->
{reverse(Acc), T};
get_quoted([$\\,C|T], Where, End, Acc) ->
get_quoted(T, Where, End, [quoted(C)|Acc]);
get_quoted([$\n|_], {File,Line}, _, _) ->
exit({error, file, File, line, Line,
"newline not allowed in string"});
get_quoted([H|T], Where, End, Acc) ->
get_quoted(T, Where, End, [H|Acc]);
get_quoted([], {File,Line}, _, _) ->
exit({error, file, File, line, Line,
"end of line not allowed in string"}).
%% Quoted characters
quoted($n) -> $\n;
quoted($t) -> $\t;
quoted($r) -> $\r;
quoted($b) -> $\b;
quoted($v) -> $\v;
quoted(C) -> C.

View File

@@ -1,73 +0,0 @@
-module(ermake_parse).
-doc([{author,'Joe Armstrong'},
{title,"Parser used by ermake."},
{keywords, [parser,make]},
{date,981029}]).
-export([parse/1]).
-import(lists, [reverse/1, prefix/2, map/2]).
parse(File) ->
Dir = filename:dirname(code:which(?MODULE)),
Lines = ermake_line_reader:read_file(File, [{"MAKEDIR", Dir}]),
map(fun parse_line/1, Lines).
parse_line({File,Line,Str}) ->
parse_str(Str).
parse_str([$S,$u,$f,$f,$i,$x,$ |T]) ->
%% io:format("Suffix:~s~n",[T]),
case split("->", T) of
{yes, Pre, Fun} ->
Tmp = string:tokens(Pre,". "),
Tmp1 = map(fun(I) -> [$.|I] end, Tmp),
{suffix, Tmp1, Fun};
no ->
exit({'No -> in suffix rule', T})
end;
parse_str(Str) ->
case split("when", Str) of
{yes, As, BsF} ->
case split("->", BsF) of
%% As when Bs -> F
{yes, Bs, F} ->
{make, parse_files(As), parse_files(Bs),
parse_fun(F)};
no ->
%% As when Bs.
{make, parse_files(As), parse_files(BsF), []}
end;
no ->
%% A -> F
case split("->", Str) of
no ->
exit({'No "when" or "->" in rule', Str});
{yes, As, F} ->
{make, parse_files(As), [true], parse_fun(F)}
end
end.
%% split(Prefix, String) -> {yes, Before, After} | no
%% splits String at Prefix
split(Prefix, L) -> split(Prefix, L, []).
split(_, [], L) ->
no;
split(Prefix, L, L1) ->
case prefix(Prefix, L) of
true ->
{yes, reverse(L1), string:substr(L, length(Prefix)+1)};
false ->
split(Prefix, tl(L), [hd(L)|L1])
end.
parse_files(Str) ->
Files = string:tokens(Str, [$ ,$,,$\n,$\t]).
parse_fun([$\n|F]) -> F;
parse_fun(F) -> F.

View File

@@ -1,30 +0,0 @@
-module(error_handler).
-doc([{author,joe},
{title,"Special version of error handler used by sos.erl"},
{date,981012}]).
-export([undefined_function/3,undefined_global_name/2]).
undefined_function(sos, F, A) ->
erlang:display({error_handler,undefined_function,
sos,F,A}),
exit(oops);
undefined_function(M, F, A) ->
case sos:load_module(M) of
{ok, M} ->
case erlang:function_exported(M,F,length(A)) of
true ->
apply(M, F, A);
false ->
sos:stop_system({undef,{M,F,A}})
end;
{ok, Other} ->
sos:stop_system({undef,{M,F,A}});
already_loaded ->
sos:stop_system({undef,{M,F,A}});
{error, What} ->
sos:stop_system({load,error,What})
end.
undefined_global_name(Name, Message) ->
exit({badarg,{Name,Message}}).

View File

@@ -1,170 +0,0 @@
-module(find).
-doc([{author,'Joe Armstrong'},
{title,"Find all files. Find all out of date files.
<p>A find utility which finds all files (and directories)
relative to a given root directory"},
{keywords, [find,make]},
{api,["find:files(\".\", \"*.erl\", false)</b> finds all
entries in the current directory.
Recursive scan of sub-directories is also allowed.",
"find:out_of_date(\".\",\".erl\",\".jam\")</b> finds all out of date
Erlang files in the current directory"]},
{date,970203}]).
-export([files/3, out_of_date/3]).
-import(lists, [suffix/2, sublist/3, map/2, filter/2]).
%% files(Dir, ReExpr, Recursive) -> [File]
%% Find regular files starting from Dir
%% Which match ReExpr
%% If Recursive is true do recursivly on all sub-directories
%% Example find(".", "*.erl", false) will find all erlang files in the
%% Current directory
%%
%% out_of_date(Dir, SrcExt, ObjExt) find all "out of date files" in
%% Dir.
%% Example:
%% out_of_date(".", ".erl", ".jam")
%% Finds all out of date files in the current directory
files(Dir, Re, Flag) ->
Re1 = string:re_sh_to_awk(Re),
find_files(Dir, Re1, Flag, []).
%% +type find_files(dirname(), Regexp, bool(), [filename()]) -> [filename()]
%% when Regexp = string().
find_files(Dir, Re, Flag, L) ->
case file:list_dir(Dir) of
{ok, Files} -> find_files(Files, Dir, Re, Flag, L);
{error, _} -> L
end.
%% +type find_files([filename()], dirname(), Regexp, bool(), [filename()]) ->
%% [filename()] when Regexp = string().
find_files([File|T], Dir, Re, Recursive, L) ->
FullName = Dir ++ [$/|File],
case file_type(FullName) of
regular ->
case string:re_match(FullName, Re) of
{match, _, _} ->
find_files(T, Dir, Re, Recursive, [FullName|L]);
_ ->
find_files(T, Dir, Re, Recursive, L)
end;
directory ->
case Recursive of
true ->
L1 = find_files(FullName, Re, Recursive, L),
find_files(T, Dir, Re, Recursive, L1);
false ->
find_files(T, Dir, Re, Recursive, L)
end;
error ->
find_files(T, Dir, Re, Recursive, L)
end;
find_files([], _, _, _, L) ->
L.
%% +type file_type(string()) -> regular | directory | error.
file_type(File) ->
case file:file_info(File) of
{ok, Facts} ->
case element(2, Facts) of
regular -> regular;
directory -> directory;
_ -> error
end;
_ ->
error
end.
%%______________________________________________________________________
%% outofdate(Dir, InExtension, OutExtension)
%% scans Dir for all files with the extension "InExtension"
%% If a file with this extension is found then "OutExtension" is checked
%%
%% returns a list of files in <Dir> where *.OutExtension is
%% "out of date" with respect to *.InExtension
%% in the sence of "make"
out_of_date(Dir, In, Out) ->
case file:list_dir(Dir) of
{ok, Files0} ->
Files1 = filter(fun(F) ->
suffix(In, F)
end, Files0),
Files2 = map(fun(F) ->
sublist(F, 1,
length(F)-length(In))
end, Files1),
filter(fun(F) -> update(F, In, Out) end,Files2);
_ ->
[]
end.
%% +type update(string(), string(), string()) -> bool().
update(File, In, Out) ->
InFile = File ++ In,
OutFile = File ++ Out,
case is_file(OutFile) of
true ->
case writeable(OutFile) of
true ->
outofdate(InFile, OutFile);
false ->
%% can't write so we can't update
false
end;
false ->
%% doesn't exist
true
end.
%% +type is_file(string()) -> bool().
is_file(File) ->
case file:file_info(File) of
{ok, _} ->
true;
_ ->
false
end.
%% +type outofdate(string(), string()) -> bool().
outofdate(In, Out) ->
case {last_modified(In), last_modified(Out)} of
{T1, T2} when T1 > T2 ->
true;
_ ->
false
end.
%% +type last_modified(string()) -> {int(), int(),int(), int(),int(), int()}
%% | 'EXIT'({last_modified, string()}).
last_modified(F) ->
case file:file_info(F) of
{ok, {_, _, _, _, Time, _, _}} ->
Time;
_ ->
exit({last_modified, F})
end.
%% +type writeable(string()) -> bool().
writeable(F) ->
case file:file_info(F) of
{ok, {_,_,read_write,_,_,_,_}} -> true;
{ok, {_,_,write ,_,_,_,_}} -> true;
_ -> false
end.

View File

@@ -1,52 +0,0 @@
-module(ftp_client).
-doc([{author, joe},
{title, "FTP client in pure Erlang -- i.e. an FTP client as it might
have been written, i.e. not according to RFC 959"},
{keywords,[ftp, client]},
{date, 981014}]).
-export([connect/3, pwd/1, cd/2, ls/1, put/2, get/2, lcd/1, lpwd/0, lls/0,
quit/1]).
connect(Host, User, Password) ->
{ftp_server, Host} ! {connect,self(),User,Password},
receive
{ftp_server, Reply} -> Reply;
Other -> Other
after 10000 ->
timeout
end.
%S tag1
pwd(Handle) -> remote(Handle, pwd).
cd(Handle, Dir) -> remote(Handle, {cd, Dir}).
ls(Handle) -> remote(Handle, ls).
get(Handle, File) -> remote(Handle, {get, File}).
quit(Handle) -> remote(Handle, quit).
%E tag1
%S tag2
lcd(Dir) -> file:set_cwd(Dir), lpwd().
lpwd() -> cwd().
lls() -> element(2, file:list_dir(cwd())).
%E tag2
cwd() -> element(2, file:get_cwd()).
remote(Handle, Op) ->
Handle ! {self(), Op},
receive
{ftp_server, Any} ->
Any
after 1000 ->
timeout
end.
put(Handle, File) ->
case file:read_file(File) of
{ok, Contents} ->
remote(Handle, {put, File, Contents});
Other ->
Other
end.

View File

@@ -1,123 +0,0 @@
-module(ftp_server).
%% Look in ~tony/erlang/ftpd/ftpd.erl
%% For filename stuff
-doc([{author, joe},
{title, "FTP server in pure Erlang -- i.e. an FTP server as it
might have been written, i.e. not according to RFC 959"},
{keywords,[ftp, server]},
{date, 981014}]).
-compile(export_all).
-export([start/0, internal/0, handler/1]).
-import(lists, [member/2, reverse/1]).
start() ->
case (catch register(ftp_server,
spawn(?MODULE, internal, []))) of
{'EXIT', _} ->
already_started;
Pid ->
ok
end.
internal() ->
case file:consult("users") of
{ok, Users} ->
process_flag(trap_exit, true),
loop(Users, 0);
_ ->
exit(no_users_allowed)
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
loop(Users, N) ->
receive
{connect, Pid, User, Password} ->
io:format("connection request from:~p ~p ~p~n",
[Pid, User, Password]),
case member({User, Password}, Users) of
true ->
Max = max_connections(),
if
N > Max ->
Pid ! {ftp_server,
{error, too_many_connections}},
loop(Users, N);
true ->
New = spawn_link(?MODULE, handler, [Pid]),
Pid ! {ftp_server, {ok, New}},
loop(Users, N + 1)
end;
false ->
Pid ! {ftp_server, {error, rejected}},
loop(Users, N)
end;
{'EXIT', Pid} ->
io:format("Handler ~p died~n", [Pid]),
loop(Users, lists:max(N-1, 0));
Any ->
io:format("received:~p~n",[Any]),
loop(Users, N)
end.
handler(Pid) ->
receive
{Pid, quit} ->
Pid ! {ftp_server, ok};
{Pid, Op} ->
io:format("got:~p ~p~n",[Pid, Op]),
Pid ! {ftp_server, do_op(Op)},
handler(Pid)
end.
do_op({cd, Dir}) -> file:set_cwd(Dir), cwd();
do_op(ls) -> element(2, file:list_dir(cwd()));
do_op(pwd) -> cwd();
do_op({get_file, File}) -> file:read_file(File).
max_connections() -> 10.
cwd() -> element(2, file:get_cwd()).
%% This was taken from Tony
%%
%% Compose file/directory names
%%
rel_name(Name, Wd) ->
case filename:pathtype(Name) of
relative ->
rel_path(filename:join(Wd, Name));
absolute ->
rel_path(Name);
volumerelative ->
rel_path(filename:join(Wd,Name))
end.
%%
%% We sometime need a simulated root, then call abs_name
%%
abs_name(Name) ->
filename:join("/", Name).
%%
%% rel_path returns a relative path i.e remove
%% and root or volume relative start components
%%
rel_path(Path) ->
rel_path(filename:split(Path),[]).
%% remove absolute or volume relative stuff
rel_path([Root|Path], RP) ->
case filename:pathtype(Root) of
relative -> rpath(Path, [Root|RP]);
_ -> rpath(Path, RP)
end.
rpath([".."|P], [_|RP]) -> rpath(P, RP);
rpath(["."|P], RP) -> rpath(P, RP);
rpath([F|P], RP) -> rpath(P, [F|RP]);
rpath([],[]) -> "";
rpath([], RP) -> filename:join(reverse(RP)).

View File

@@ -1,591 +0,0 @@
%% THIS IS A PRE-RELEASE OF LEEX - RELEASED ONLY BECAUSE MANY PEOPLE
%% WANTED IT - THE OFFICIAL RELEASE WILL PROVIDE A DIFFERENT INCOMPATIBLE
%% AND BETTER INTERFACE - BE WARNED
%% PLEASE REPORT ALL BUGS TO THE AUTHOR.
%% Copyright (C) 1996, Ellemtel Telecommunications Systems Laboratories
%% File : leex.erl
%% Author : Robert Virding (rv@cslab.ericsson.se)
%% Purpose : A Lexical Analyser Generator for Erlang.
%% Most of the algorithms used here are taken pretty much as
%% described in the "Dragon Book" by Aho, Sethi and Ullman. Some
%% completing details were taken from "Compiler Design in C" by
%% Hollub.
-module(leex).
-doc([{author,'Robert Virding'},
{title,"A Lexical Analyser Generator for Erlang"},
{keywords, [lex]},
{date,981012}]).
-copyright('Copyright (c) 1996 Ericsson Telecommunications AB').
-author('rv@cslab.ericsson.se').
-export([gen/2,format_error/1]).
-import(lists, [member/2,reverse/1,seq/2,keymember/3,keysearch/3,keysort/2,
foreach/2]).
-import(ordsets, [is_element/2,add_element/2,union/2,subtract/2]).
%%-compile([export_all]).
-record(nfa_state, {no,edges=[],accept=noaccept}).
-record(dfa_state, {no,nfa=[],trans=[],accept=noaccept}).
gen(In, Out) ->
InFile = lists:concat([In,".xrl"]),
OutFile = lists:concat([Out,".erl"]),
case parse_file(InFile) of
{ok,REAs,Actions,Code} ->
%% io:fwrite("REAs = ~p\n", [REAs]),
%% io:fwrite("Actions = ~p\n", [Actions]),
{NFA,NF} = build_combined_nfa(REAs),
io:fwrite("NFA contains ~w states, ", [size(NFA)]),
%% io:fwrite("NFA = ~p~n ", [NFA]),
{DFA0,DF0} = build_dfa(NFA, NF),
io:fwrite("DFA contains ~w states, ", [length(DFA0)]),
%% io:fwrite("DFA = ~p~n ", [DFA0]),
{DFA,DF} = minimise_dfa(DFA0, DF0),
io:fwrite("minimised to ~w states.~n", [length(DFA)]),
out_file(OutFile, Out, DFA, DF, Actions, Code);
{error,Error} ->
io:put_chars([$\n,gcc_error(InFile, Error),$\n]),
error
end.
format_error({open,F}) -> ["error opening ",io_lib:write_string(F)];
format_error(missing_rules) -> "missing rules";
format_error(bad_rule) -> "bad rule";
format_error({regexp,E}) -> ["bad regexp `",regexp:format_error(E),"'"];
format_error({after_regexp,S}) ->
["bad code after regexp ",io_lib:write_string(S)].
gcc_error(File, {Line,Mod,Error}) ->
io_lib:format("~s:~w: ~s", [File,Line,apply(Mod, format_error, [Error])]);
gcc_error(File, {Mod,Error}) ->
io_lib:format("~s: ~s", [File,apply(Mod, format_error, [Error])]).
%% parse_file(InFile) -> {[REA],[Action],Code} | {error,Error}
%% when
%% REA = {RegExp,ActionNo};
%% Action = {ActionNo,ActionString};
%% Code = [char()].
%%
%% Read and parse the file InFile.
%% After each section of the file has been parsed we directly call the
%% next section. This is done when we detect a line we don't recognise
%% in the current section. The file format is very simple and Erlang
%% token based, we allow empty lines and Erlang style comments.
parse_file(InFile) ->
case file:open(InFile, read) of
{ok,Ifile} ->
io:fwrite("Parsing file ~s, ", [InFile]),
case parse_head(Ifile) of
{ok,REAs,Actions,Code} ->
io:fwrite("contained ~w rules.~n", [length(REAs)]),
file:close(Ifile),
{ok,REAs,Actions,Code};
Error ->
file:close(Ifile),
Error
end;
{error,R} ->
{error,{leex,{open,InFile}}}
end.
%% parse_head(File)
%% Parse the head of the file.
parse_head(Ifile) ->
parse_defs(Ifile, nextline(Ifile, 0)).
%% parse_defs(File, Line)
%% Parse the macro definition section of a file. Allow no definitions.
parse_defs(Ifile, {ok,[$D,$e,$f,$i,$n,$i,$t,$i,$o,$n,$s,$.|_Rest],L}) ->
parse_defs(Ifile, nextline(Ifile, L), []);
parse_defs(Ifile, Line) ->
parse_rules(Ifile, Line, []).
parse_defs(Ifile, {ok,Chars,L}, Ms) ->
case string:tokens(Chars, " \t\n") of
[Name,"=",Def] ->
parse_defs(Ifile, nextline(Ifile, L), [{Name,Def}|Ms]);
Other ->
parse_rules(Ifile, {ok,Chars,L}, Ms)
end;
parse_defs(Ifile, Line, Ms) ->
parse_rules(Ifile, Line, Ms).
%% parse_rules(File, Line, Macros)
%% Parse the RE rules section of the file. This must exist.
parse_rules(Ifile, {ok,[$R,$u,$l,$e,$s,$.|_Rest],L}, Ms) ->
parse_rules(Ifile, nextline(Ifile, L), Ms, [], [], 0);
parse_rules(Ifile, {ok,Other,L}, Ms) ->
{error,{L,leex,missing_rules}};
parse_rules(Ifile, {eof,L}, Ms) ->
{error,{L,leex,missing_rules}}.
collect_rule(Ifile, Chars, L0) ->
{match,St,Len} = regexp:first_match(Chars, "[^ \t]+"),
%% io:fwrite("RE = ~p~n", [string:substr(Chars, St, Len)]),
case collect_rule(Ifile, string:substr(Chars, St+Len), L0, []) of
{ok,[{':',Lc}|Toks],L1} -> {ok,string:substr(Chars, St, Len),Toks,L1};
{ok,Toks,L1} -> {error,{L0,leex,bad_rule}};
{eof,L1} -> {error,{L1,leex,bad_rule}};
{error,E,L1} -> {error,E}
end.
collect_rule(Ifile, Chars, L0, Cont0) ->
case erl_scan:tokens(Cont0, Chars, L0) of
{done,{ok,Toks,L1},Rest} -> {ok,Toks,L0};
{done,{eof,L1},Rest} -> {eof,L0};
{done,{error,E,L1},Rest} -> {error,E,L0};
{more,Cont1} ->
collect_rule(Ifile, io:get_line(Ifile, leex), L0+1, Cont1)
end.
parse_rules(Ifile, {ok,[$E,$r,$l,$a,$n,$g,$ ,$c,$o,$d,$e,$.|_Rest],L},
Ms, REAs, As, N) ->
%% Must be careful to put rules in correct order!
parse_code(Ifile, L, reverse(REAs), reverse(As));
parse_rules(Ifile, {ok,Chars,L0}, Ms, REAs, As, N) ->
%% io:fwrite("~w: ~p~n", [L0,Chars]),
case collect_rule(Ifile, Chars, L0) of
{ok,Re,Atoks,L1} ->
case parse_rule(Re, L0, Atoks, Ms, N) of
{ok,REA,A} ->
parse_rules(Ifile, nextline(Ifile, L1), Ms,
[REA|REAs], [A|As], N+1);
{error,E} -> {error,E}
end;
{error,E} -> {error,E}
end;
parse_rules(Ifile, {eof,Line}, Ms, REAs, As, N) ->
%% Must be careful to put rules in correct order!
{ok,reverse(REAs),reverse(As),[]}.
%% parse_rule(RegExpString, RegExpLine, ActionTokens, Macros, Counter)
%% Parse one regexp after performing macro substition.
parse_rule(S, Line, [{dot,Ld}], Ms, N) ->
case parse_rule_regexp(S, Ms) of
{ok,R} ->
{ok,{R,N},{N,empty_action}};
{error,E} ->
{error,{Line,leex,{regexp,E}}}
end;
parse_rule(S, Line, Atoks, Ms, N) ->
case parse_rule_regexp(S, Ms) of
{ok,R} ->
case erl_parse:parse_exprs(Atoks) of
{ok,Aes} ->
YYtext = keymember('YYtext', 3, Atoks),
{ok,{R,N},{N,Aes,YYtext}};
{error,E} ->
{error,{Line,leex,{after_regexp,S}}}
end;
{error,E} ->
{error,{Line,leex,{regexp,E}}}
end.
parse_rule_regexp(RE0, [{M,Exp}|Ms]) ->
case regexp:gsub(RE0, "{" ++ M ++ "}", Exp) of
{ok,RE,N} -> parse_rule_regexp(RE, Ms);
{error,E} -> parse_rule_regexp(RE0, Ms)
end;
parse_rule_regexp(RE, []) ->
%% io:fwrite("RE = ~p~n", [RE]),
regexp:parse(RE).
%% parse_code(File, Line, REAs, Actions)
%% Parse the code section of the file.
parse_code(Ifile, Line, REAs, As) ->
{ok,REAs,As,io:get_chars(Ifile, leex, 102400)}.
%% nextline(InputFile, PrevLineNo) -> {ok,Chars,LineNo} | {eof,LineNo}.
%% Get the next line skipping comment lines and blank lines.
nextline(Ifile, L) ->
case io:get_line(Ifile, leex) of
eof -> {eof,L};
Chars ->
case skip(Chars, " \t\n") of
[$%|_Rest] -> nextline(Ifile, L+1);
[] -> nextline(Ifile, L+1);
Other -> {ok,Chars,L+1}
end
end.
%% skip(Str, Cs) -> lists:dropwhile(fun (C) -> member(C, Cs) end, Str).
skip([C|Str], Cs) ->
case member(C, Cs) of
true -> skip(Str, Cs);
false -> [C|Str]
end;
skip([], Cs) -> [].
%% build_combined_nfa(RegExpActionList) -> {NFA,FirstState}. Build
%% the combined NFA using Thompson's construction straight out of the
%% book. Build the separate NFAs in the same order as the rules so
%% that the accepting have ascending states have ascending state
%% numbers. Start numbering the states from 1 as we put the states
%% in a tuple with the state number as the index.
build_combined_nfa(REAs) ->
{NFA0,Firsts,Free} = build_nfa_list(REAs, [], [], 1),
F = #nfa_state{no=Free,edges=epsilon_trans(Firsts)},
{list_to_tuple(keysort(#nfa_state.no, [F|NFA0])),Free}.
build_nfa_list([{RE,Action}|REAs], NFA0, Firsts, Free0) ->
{NFA1,Free1,First} = build_nfa(RE, Free0, Action),
build_nfa_list(REAs, NFA1 ++ NFA0, [First|Firsts], Free1);
build_nfa_list([], NFA, Firsts, Free) ->
{NFA,reverse(Firsts),Free}.
epsilon_trans(Firsts) -> [ {epsilon,F} || F <- Firsts ].
%% {NFA,NextFreeState,FirstState} = build_nfa(RegExp, FreeState, Action)
%% When building the NFA states for a ??? we don't build the end
%% state, just allocate a State for it and return this state
%% number. This allows us to avoid building unnecessary states for
%% concatenation which would then have to be removed by overwriting
%% an existing state.
build_nfa(RE, FreeState, Action) ->
{NFA,N,Es} = build_nfa(RE, FreeState+1, FreeState, []),
{[#nfa_state{no=Es,accept={accept,Action}}|NFA],N,FreeState}.
%% build_nfa(RegExp, NextState, FirstState, NFA) -> {NFA,NextState,EndState}.
%% The NFA is a list of nfa_state is no predefined order. The state
%% number of the returned EndState is already allocated!
build_nfa({'or',RE1,RE2}, N0, Fs, NFA0) ->
{NFA1,N1,Es1} = build_nfa(RE1, N0+1, N0, NFA0),
{NFA2,N2,Es2} = build_nfa(RE2, N1+1, N1, NFA1),
Es = N2,
{[#nfa_state{no=Fs,edges=[{epsilon,N0},{epsilon,N1}]},
#nfa_state{no=Es1,edges=[{epsilon,Es}]},
#nfa_state{no=Es2,edges=[{epsilon,Es}]}|NFA2],
N2+1,Es};
build_nfa({concat,RE1, RE2}, N0, Fs, NFA0) ->
{NFA1,N1,Es1} = build_nfa(RE1, N0, Fs, NFA0),
{NFA2,N2,Es2} = build_nfa(RE2, N1, Es1, NFA1),
{NFA2,N2,Es2};
build_nfa({kclosure,RE}, N0, Fs, NFA0) ->
{NFA1,N1,Es1} = build_nfa(RE, N0+1, N0, NFA0),
Es = N1,
{[#nfa_state{no=Fs,edges=[{epsilon,N0},{epsilon,Es}]},
#nfa_state{no=Es1,edges=[{epsilon,N0},{epsilon,Es}]}|NFA1],
N1+1,Es};
build_nfa({pclosure,RE}, N0, Fs, NFA0) ->
{NFA1,N1,Es1} = build_nfa(RE, N0+1, N0, NFA0),
Es = N1,
{[#nfa_state{no=Fs,edges=[{epsilon,N0}]},
#nfa_state{no=Es1,edges=[{epsilon,N0},{epsilon,Es}]}|NFA1],
N1+1,Es};
build_nfa({optional,RE}, N0, Fs, NFA0) ->
{NFA1,N1,Es1} = build_nfa(RE, N0+1, N0, NFA0),
Es = N1,
{[#nfa_state{no=Fs,edges=[{epsilon,N0},{epsilon,Es}]},
#nfa_state{no=Es1,edges=[{epsilon,Es}]}|NFA1],
N1+1,Es};
build_nfa({char_class,Cc}, N, Fs, NFA) ->
{[#nfa_state{no=Fs,edges=[{char_class(Cc),N}]}|NFA],N+1,N};
build_nfa({comp_class,Cc}, N, Fs, NFA) ->
{[#nfa_state{no=Fs,edges=[{comp_class(Cc),N}]}|NFA],N+1,N};
build_nfa(C, N, Fs, NFA) when integer(C) ->
{[#nfa_state{no=Fs,edges=[{[C],N}]}|NFA],N+1,N}.
char_class(Cc) ->
lists:foldl(fun ({C1,C2}, Set) -> union(seq(C1, C2), Set);
(C, Set) -> add_element(C, Set) end, [], Cc).
comp_class(Cc) -> subtract(seq(0, 255), char_class(Cc)).
%% build_dfa(NFA, NfaFirstState) -> {DFA,DfaFirstState}.
%% Build a DFA from an NFA using "subset construction". The major
%% difference from the book is that we keep the marked and unmarked
%% DFA states in seperate lists. New DFA states are added to the
%% unmarked list and states are marked by moving them to the marked
%% list. We assume that the NFA accepting state numbers are in
%% ascending order for the rules and use ordsets to keep this order.
build_dfa(NFA, Nf) ->
D = #dfa_state{no=0,nfa=eclosure([Nf], NFA)},
{build_dfa([D], 1, [], NFA),0}.
%% build_dfa([UnMarked], NextState, [Marked], NFA) -> DFA.
%% Traverse the unmarked states. Temporarily add the current unmarked
%% state to the marked list before calculating translation, this is
%% to avoid adding too many duplicate states. Add it properly to the
%% marked list afterwards with correct translations.
build_dfa([U|Us0], N0, Ms, NFA) ->
{Ts,Us1,N1} = build_dfa(255, U#dfa_state.nfa, Us0, N0, [], [U|Ms], NFA),
M = U#dfa_state{trans=Ts,accept=accept(U#dfa_state.nfa, NFA)},
build_dfa(Us1, N1, [M|Ms], NFA);
build_dfa([], N, Ms, NFA) -> Ms.
%% build_dfa(Char, [NfaState], [Unmarked], NextState, [Transition], [Marked], NFA) ->
%% [Marked].
%% Foreach NFA state set calculate the legal translations. N.B. must
%% search *BOTH* the unmarked and marked lists to check if DFA state
%% already exists. By test characters downwards and prepending
%% transitions we get the transition lists in ascending order.
build_dfa(C, Set, Us, N, Ts, Ms, NFA) when C >= 0 ->
case eclosure(move(Set, C, NFA), NFA) of
S when S /= [] ->
case keysearch(S, #dfa_state.nfa, Us) of
{value,#dfa_state{no=T}} ->
build_dfa(C-1, Set, Us, N, [{C,T}|Ts], Ms, NFA);
false ->
case keysearch(S, #dfa_state.nfa, Ms) of
{value,#dfa_state{no=T}} ->
build_dfa(C-1, Set, Us, N, [{C,T}|Ts], Ms, NFA);
false ->
U = #dfa_state{no=N,nfa=S},
build_dfa(C-1, Set, [U|Us], N+1, [{C,N}|Ts], Ms, NFA)
end
end;
[] ->
build_dfa(C-1, Set, Us, N, Ts, Ms, NFA)
end;
build_dfa(-1, Set, Us, N, Ts, Ms, NFA) ->
{Ts,Us,N}.
%% eclosure([State], NFA) -> [State].
%% move([State], Char, NFA) -> [State].
%% These are straight out of the book. As eclosure uses ordsets then
%% the generated state sets are in ascending order.
eclosure(Sts, NFA) -> eclosure(Sts, NFA, []).
eclosure([St|Sts], NFA, Ec) ->
#nfa_state{edges=Es} = element(St, NFA),
eclosure([ N || {epsilon,N} <- Es,
nnot(is_element(N, Ec)) ] ++ Sts,
NFA, add_element(St, Ec));
eclosure([], NFA, Ec) -> Ec.
nnot(true) -> false;
nnot(false) -> true.
move(Sts, C, NFA) ->
[St || N <- Sts,
{C1,St} <- (element(N, NFA))#nfa_state.edges,
list(C1),
member(C, C1) ].
%% accept([State], NFA) -> {accept,A} | noaccept.
%% Scan down the state list until we find an accepting state.
accept([St|Sts], NFA) ->
case element(St, NFA) of
#nfa_state{accept={accept,A}} -> {accept,A};
#nfa_state{accept=noaccept} -> accept(Sts, NFA)
end;
accept([], NFA) -> noaccept.
%% minimise_dfa(DFA, DfaFirst) -> {DFA,DfaFirst}.
%% Minimise the DFA by removing equivalent states. We consider a
%% state if both the transitions and the their accept state is the
%% same. First repeatedly run throught the DFA state list removing
%% equivalent states and updating remaining transitions with
%% remaining equivalent state numbers. When no more reductions are
%% possible then pack the remaining state numbers to get consecutive
%% states.
minimise_dfa(DFA0, Df0) ->
case min_dfa(DFA0) of
{DFA1,[]} -> %No reduction!
{DFA2,Rs} = pack_dfa(DFA1),
{min_update(DFA2, Rs),min_use(Df0, Rs)};
{DFA1,Rs} ->
minimise_dfa(min_update(DFA1, Rs), min_use(Df0, Rs))
end.
min_dfa(DFA) -> min_dfa(DFA, [], []).
min_dfa([D|DFA0], Rs0, MDFA) ->
{DFA1,Rs1} = min_delete(DFA0, D#dfa_state.trans, D#dfa_state.accept,
D#dfa_state.no, Rs0, []),
min_dfa(DFA1, Rs1, [D|MDFA]);
min_dfa([], Rs, MDFA) -> {MDFA,Rs}.
min_delete([#dfa_state{no=N,trans=T,accept=A}|DFA], T, A, NewN, Rs, MDFA) ->
min_delete(DFA, T, A, NewN, [{N,NewN}|Rs], MDFA);
min_delete([D|DFA], T, A, NewN, Rs, MDFA) ->
min_delete(DFA, T, A, NewN, Rs, [D|MDFA]);
min_delete([], T, A, NewN, Rs, MDFA) -> {MDFA,Rs}.
min_update(DFA, Rs) ->
[ D#dfa_state{trans=min_update_trans(D#dfa_state.trans, Rs)} || D <- DFA ].
min_update_trans(Tr, Rs) ->
[ {C,min_use(S, Rs)} || {C,S} <- Tr ].
min_use(Old, [{Old,New}|Reds]) -> New;
min_use(Old, [R|Reds]) -> min_use(Old, Reds);
min_use(Old, []) -> Old.
pack_dfa(DFA) -> pack_dfa(DFA, 0, [], []).
pack_dfa([D|DFA], NewN, Rs, PDFA) ->
pack_dfa(DFA, NewN+1, [{D#dfa_state.no,NewN}|Rs], [D#dfa_state{no=NewN}|PDFA]);
pack_dfa([], NewN, Rs, PDFA) -> {PDFA,Rs}.
%% out_file(FileName, Module, DFA, DfaStart, [Action], Code) -> ok | error.
out_file(OutFile, Out, DFA, DF, Actions, Code) ->
io:fwrite("Writing file ~s, ", [OutFile]),
case file:path_open([".", [code:lib_dir(),"/tools/include"]],
"leex.hrl", read) of
{ok,Ifile,Iname} ->
case file:open(OutFile, write) of
{ok,Ofile} ->
out_file(Ifile, Ofile, Out, DFA, DF, Actions, Code),
file:close(Ifile),
file:close(Ofile),
io:fwrite("ok~n"),
ok;
{error,E} ->
file:close(Ifile),
io:fwrite("open error~n"),
error
end;
{error,R} ->
io:fwrite("open error~n"),
error
end.
%% out_file(IncFile, OutFile, DFA, DfaStart, Actions, Code) -> ok.
%% Copy the include file line by line substituting special lines with
%% generated code. We cheat by only looking at the first 5
%% characters.
out_file(Ifile, Ofile, Out, DFA, DF, Actions, Code) ->
case io:get_line(Ifile, leex) of
eof -> ok;
Line ->
case string:substr(Line, 1, 5) of
"##mod" -> io:fwrite(Ofile, "-module(~w).~n", [Out]);
"##cod" -> io:put_chars(Ofile, Code);
"##dfa" -> out_dfa(Ofile, DFA, DF);
"##act" -> out_actions(Ofile, Actions);
Other -> io:put_chars(Ofile, Line)
end,
out_file(Ifile, Ofile, Out, DFA, DF, Actions, Code)
end.
out_dfa(File, DFA, DF) ->
io:fwrite(File, "yystate() -> ~w.~n~n", [DF]),
foreach(fun (S) -> out_trans(File, S) end, DFA),
io:fwrite(File, "yystate(S, Ics, Line, Tlen, Action, Alen) ->~n", []),
io:fwrite(File, " {Action,Alen,Tlen,Ics,Line,S}.~n~n", []).
out_trans(File, #dfa_state{no=N,trans=[],accept={accept,A}}) ->
io:fwrite(File, "yystate(~w, Ics, Line, Tlen, Action, Alen) ->~n", [N]),
io:fwrite(File, " {~w,Tlen,Ics,Line};~n", [A]);
out_trans(File, #dfa_state{no=N,trans=Tr,accept={accept,A}}) ->
foreach(fun (T) -> out_tran(File, N, A, T) end, pack_trans(Tr)),
io:fwrite(File, "yystate(~w, Ics, Line, Tlen, Action, Alen) ->~n", [N]),
io:fwrite(File, " {~w,Tlen,Ics,Line,~w};~n", [A,N]);
out_trans(File, #dfa_state{no=N,trans=Tr,accept=noaccept}) ->
foreach(fun (T) -> out_tran(File, N, T) end, pack_trans(Tr)),
io:fwrite(File, "yystate(~w, Ics, Line, Tlen, Action, Alen) ->~n", [N]),
io:fwrite(File, " {Action,Alen,Tlen,Ics,Line,~w};~n", [N]).
out_tran(File, N, A, {{Cf,Cl},S}) ->
out_head(File, N, io_lib:write_char(Cf), io_lib:write_char(Cl)),
out_body(File, S, "Line", "C", A);
out_tran(File, N, A, {$\n,S}) ->
out_head(File, N, "$\\n"),
out_body(File, S, "Line+1", "$\\n", A);
out_tran(File, N, A, {C,S}) ->
Char = io_lib:write_char(C),
out_head(File, N, Char),
out_body(File, S, "Line", Char, A).
out_tran(File, N, {{Cf,Cl},S}) ->
out_head(File, N, io_lib:write_char(Cf), io_lib:write_char(Cl)),
out_body(File, S, "Line", "C");
out_tran(File, N, {$\n,S}) ->
out_head(File, N, "$\\n"),
out_body(File, S, "Line+1", "$\\n");
out_tran(File, N, {C,S}) ->
Char = io_lib:write_char(C),
out_head(File, N, Char),
out_body(File, S, "Line", Char).
out_head(File, State, Char) ->
io:fwrite(File, "yystate(~w, [~s|Ics], Line, Tlen, Action, Alen) ->\n",
[State,Char]).
out_head(File, State, Min, Max) ->
io:fwrite(File, "yystate(~w, [C|Ics], Line, Tlen, Action, Alen) when C >= ~s, C =< ~s ->\n",
[State,Min,Max]).
out_body(File, Next, Line, C, Action) ->
io:fwrite(File, " yystate(~w, Ics, ~s, Tlen+1, ~w, Tlen);\n",
[Next,Line,Action]).
out_body(File, Next, Line, C) ->
io:fwrite(File, " yystate(~w, Ics, ~s, Tlen+1, Action, Alen);\n",
[Next,Line]).
%% pack_tran([{Char,State}]) -> [{Crange,State}] when
%% Crange = {Char,Char} | Char.
%% Pack the translation table into something more suitable for
%% generating code. Ranges of characters with the same State are
%% packed together, while solitary characters are left "as is". We
%% KNOW how the pattern matching compiler works so solitary
%% characters are stored before ranges. We do this using ordsets for
%% for the packed table. Always break out $\n as solitary character.
pack_trans([{C,S}|Tr]) -> pack_trans(Tr, C, C, S, []);
pack_trans([]) -> [].
pack_trans([{$\n,S1}|Tr], Cf, Cl, S, Pt) ->
pack_trans(Cf, Cl, S, add_element({$\n,S1}, pack_trans(Tr)));
pack_trans([{C,S}|Tr], Cf, Cl, S, Pt) when C == Cl + 1 ->
pack_trans(Tr, Cf, C, S, Pt);
pack_trans([{C,S1}|Tr], Cf, Cl, S, Pt) ->
pack_trans(Tr, C, C, S1, pack_trans(Cf, Cl, S, Pt));
pack_trans([], Cf, Cl, S, Pt) -> pack_trans(Cf, Cl, S, Pt).
pack_trans(Cf, Cf, S, Pt) -> add_element({Cf,S}, Pt);
pack_trans(Cf, Cl, S, Pt) when Cl == Cf + 1 ->
add_element({Cf,S}, add_element({Cl,S}, Pt));
pack_trans(Cf, Cl, S, Pt) -> add_element({{Cf,Cl},S}, Pt).
out_actions(File, As) ->
foreach(fun (A) -> out_action(File, A) end, As),
io:fwrite(File, "yyaction(_, _, _, _) -> error.~n", []).
out_action(File, {A,empty_action}) ->
io:fwrite(File, "yyaction(~w, YYlen, YYtcs, YYline) -> skip_token;~n", [A]);
out_action(File, {A,Code,YYtext}) ->
io:fwrite(File, "yyaction(~w, YYlen, YYtcs, YYline) ->~n", [A]),
if
YYtext == true ->
io:fwrite(File, " YYtext = yypre(YYtcs, YYlen),~n", []);
YYtext == false -> ok
end,
io:fwrite(File, " ~s;~n", [erl_pp:exprs(Code, 4, none)]).

View File

@@ -1,200 +0,0 @@
%% THIS IS A PRE-RELEASE OF LEEX - RELEASED ONLY BECAUSE MANY PEOPLE
%% WANTED IT - THE OFFICIAL RELEASE WILL PROVIDE A DIFFERENT INCOMPATIBLE
%% AND BETTER INTERFACE - BE WARNED
%% PLEASE REPORT ALL BUGS TO THE AUTHOR.
##module
-export([string/1,string/2,token/2,token/3,tokens/2,tokens/3]).
-export([format_error/1]).
%% User code. This is placed here to allow extra attributes.
##code
format_error({illegal,S}) -> ["illegal characters ",io_lib:write_string(S)];
format_error({user,S}) -> S.
string(String) -> string(String, 1).
string(String, Line) -> string(String, Line, String, []).
%% string(InChars, Line, TokenChars, Tokens) ->
%% {ok,Tokens,Line} | {error,ErrorInfo,Line}.
string([], L, [], Ts) -> %No partial tokens!
{ok,yyrev(Ts),L};
string(Ics0, L0, Tcs, Ts) ->
case yystate(yystate(), Ics0, L0, 0, reject, 0) of
{A,Alen,Ics1,L1} -> %Accepting end state
string_cont(Ics1, L1, yyaction(A, Alen, Tcs, L1), Ts);
{A,Alen,Ics1,L1,S1} -> %After an accepting state
string_cont(Ics1, L1, yyaction(A, Alen, Tcs, L1), Ts);
{reject,Alen,Tlen,Ics1,L1,S1} ->
{error,{L1,?MODULE,{illegal,yypre(Tcs, Tlen+1)}},L1};
{A,Alen,Tlen,Ics1,L1,S1} ->
string_cont(yysuf(Tcs, Alen), L1, yyaction(A, Alen, Tcs, L1), Ts)
end.
%% string_cont(RestChars, Line, Token, Tokens)
%% Test for and remove the end token wrapper.
string_cont(Rest, Line, {token,T}, Ts) ->
string(Rest, Line, Rest, [T|Ts]);
string_cont(Rest, Line, {end_token,T}, Ts) ->
string(Rest, Line, Rest, [T|Ts]);
string_cont(Rest, Line, skip_token, Ts) ->
string(Rest, Line, Rest, Ts);
string_cont(Rest, Line, {error,S}, Ts) ->
{error,{Line,?MODULE,{user,S}},Line}.
%% token(Continuation, Chars, Line) ->
%% {more,Continuation} | {done,ReturnVal,RestChars}.
%% Must be careful when re-entering to append the latest characters to the
%% after characters in an accept.
token(Cont, Chars) -> token(Cont, Chars, 1).
token([], Chars, Line) ->
token(Chars, Line, yystate(), Chars, 0, reject, 0);
token({Line,State,Tcs,Tlen,Action,Alen}, Chars, _) ->
token(Chars, Line, State, Tcs ++ Chars, Tlen, Action, Alen).
%% token(InChars, Line, State, TokenChars, TokenLen, Accept) ->
%% {more,Continuation} | {done,ReturnVal,RestChars}.
token(Ics0, L0, S0, Tcs, Tlen0, A0, Alen0) ->
case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of
{A1,Alen1,Ics1,L1} -> %Accepting end state
token_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1));
{A1,Alen1,[],L1,S1} -> %After an accepting state
{more,{L1,S1,Tcs,Alen1,A1,Alen1}};
{A1,Alen1,Ics1,L1,S1} ->
token_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1));
{A1,Alen1,Tlen1,[],L1,S1} -> %After a non-accepting state
{more,{L1,S1,Tcs,Tlen1,A1,Alen1}};
{reject,Alen1,Tlen1,eof,L1,S1} ->
{done,{eof,L1},[]};
{reject,Alen1,Tlen1,Ics1,L1,S1} ->
{done,{error,{L1,?MODULE,{illegal,yypre(Tcs, Tlen1+1)}},L1},Ics1};
{A1,Alen1,Tlen1,Ics1,L1,S1} ->
token_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, L1))
end.
%% tokens_cont(RestChars, Line, Token)
%% Test if we have detected the end token, if so return done else continue.
token_cont(Rest, Line, {token,T}) ->
{done,{ok,T,Line},Rest};
token_cont(Rest, Line, {end_token,T}) ->
{done,{ok,T,Line},Rest};
token_cont(Rest, Line, skip_token) ->
token(Rest, Line, yystate(), Rest, 0, reject, 0);
token_cont(Rest, Line, {error,S}) ->
{done,{error,{Line,?MODULE,{user,S}},Line},Rest}.
%% tokens(Continuation, Chars, Line) ->
%% {more,Continuation} | {done,ReturnVal,RestChars}.
%% Must be careful when re-entering to append the latest characters to the
%% after characters in an accept.
tokens(Cont, Chars) -> tokens(Cont, Chars, 1).
tokens([], Chars, Line) ->
tokens(Chars, Line, yystate(), Chars, 0, [], reject, 0);
tokens({tokens,Line,State,Tcs,Tlen,Ts,Action,Alen}, Chars, _) ->
tokens(Chars, Line, State, Tcs ++ Chars, Tlen, Ts, Action, Alen);
tokens({skip_tokens,Line,State,Tcs,Tlen,Error,Action,Alen}, Chars, _) ->
skip_tokens(Chars, Line, State, Tcs ++ Chars, Tlen, Error, Action, Alen).
%% tokens(InChars, Line, State, TokenChars, TokenLen, Tokens, Accept) ->
%% {more,Continuation} | {done,ReturnVal,RestChars}.
tokens(Ics0, L0, S0, Tcs, Tlen0, Ts, A0, Alen0) ->
case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of
{A1,Alen1,Ics1,L1} -> %Accepting end state
tokens_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Ts);
{A1,Alen1,[],L1,S1} -> %After an accepting state
{more,{tokens,L1,S1,Tcs,Alen1,Ts,A1,Alen1}};
{A1,Alen1,Ics1,L1,S1} ->
tokens_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Ts);
{A1,Alen1,Tlen1,[],L1,S1} -> %After a non-accepting state
{more,{tokens,L1,S1,Tcs,Tlen1,Ts,A1,Alen1}};
{reject,Alen1,Tlen1,eof,L1,S1} ->
{done,if Ts == [] -> {eof,L1};
true -> {ok,yyrev(Ts),L1} end,[]};
{reject,Alen1,Tlen1,Ics1,L1,S1} ->
skip_tokens(yysuf(Tcs, Tlen1+1), L1,
{L1,?MODULE,{illegal,yypre(Tcs, Tlen1+1)}});
{A1,Alen1,Tlen1,Ics1,L1,S1} ->
tokens_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, L1), Ts)
end.
%% tokens_cont(RestChars, Line, Token, Tokens)
%% Test if we have detected the end token, if so return done else continue.
tokens_cont(Rest, Line, {token,T}, Ts) ->
tokens(Rest, Line, yystate(), Rest, 0, [T|Ts], reject, 0);
tokens_cont(Rest, Line, {end_token,T}, Ts) ->
{done,{ok,yyrev(Ts, [T]),Line},Rest};
tokens_cont(Rest, Line, skip_token, Ts) ->
tokens(Rest, Line, yystate(), Rest, 0, Ts, reject, 0);
tokens_cont(Rest, Line, {error,S}, Ts) ->
skip_tokens(Rest, Line, {Line,?MODULE,{user,S}}).
%% token_skip(InChars, Line, Error) -> {done,ReturnVal,RestChars}.
%% Skip tokens until an end token, junk everything and return the error.
%%skip_tokens(Ics, Line, Error) -> {done,{error,Error,Line},Ics}.
skip_tokens(Ics, Line, Error) ->
skip_tokens(Ics, Line, yystate(), Ics, 0, Error, reject, 0).
%% skip_tokens(InChars, Line, State, TokenChars, TokenLen, Tokens, Accept) ->
%% {more,Continuation} | {done,ReturnVal,RestChars}.
skip_tokens(Ics0, L0, S0, Tcs, Tlen0, Error, A0, Alen0) ->
case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of
{A1,Alen1,Ics1,L1} -> %Accepting end state
skip_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Error);
{A1,Alen1,[],L1,S1} -> %After an accepting state
{more,{skip_tokens,L1,S1,Tcs,Alen1,Error,A1,Alen1}};
{A1,Alen1,Ics1,L1,S1} ->
skip_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Error);
{A1,Alen1,Tlen1,[],L1,S1} -> %After a non-accepting state
{more,{skip_tokens,L1,S1,Tcs,Tlen1,Error,A1,Alen1}};
{reject,Alen1,Tlen1,eof,L1,S1} ->
{done,{error,Error,L1},[]};
{reject,Alen1,Tlen1,Ics1,L1,S1} ->
skip_tokens(yysuf(Tcs, Tlen1), L1, Error);
{A1,Alen1,Tlen1,Ics1,L1,S1} ->
skip_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, L1), Error)
end.
%% skip_cont(RestChars, Line, Token, Error)
%% Test if we have detected the end token, if so return done else continue.
skip_cont(Rest, Line, {token,T}, Error) ->
skip_tokens(Rest, Line, yystate(), Rest, 0, Error, reject, 0);
skip_cont(Rest, Line, {end_token,T}, Error) ->
{done,{error,Error,Line},Rest};
skip_cont(Rest, Line, {error,S}, Error) ->
skip_tokens(Rest, Line, yystate(), Rest, 0, Error, reject, 0);
skip_cont(Rest, Line, skip_token, Error) ->
skip_tokens(Rest, Line, yystate(), Rest, 0, Error, reject, 0).
yyrev(L) -> yyrev(L, []).
yyrev([H|T], Acc) -> yyrev(T, [H|Acc]);
yyrev([], Acc) -> Acc.
yypre([H|T], N) when N > 0 -> [H|yypre(T, N-1)];
yypre(L, N) -> [].
yysuf([H|T], N) when N > 0 -> yysuf(T, N-1);
yysuf(L, 0) -> L.
%% Generated state transition function.
##dfa
%% Generated action function.
##actions

View File

@@ -1,95 +0,0 @@
-module(lin).
-doc([{author,'Joe Armstrong'},
{title,"Linear algebra utilities."},
{keywords, [linear,algebra]},
{date,981103}]).
-export([pow/3, inv/2, solve/2, str2int/1, int2str/1, gcd/2]).
%% pow(A, B, M) => (A^B) mod M
%% examples pow(9726,3533,11413) = 5761
%% pow(5971,6597,11413) = 9726
pow(A, 1, M) ->
A rem M;
pow(A, 2, M) ->
A*A rem M;
pow(A, B, M) ->
B1 = B div 2,
B2 = B - B1,
%% B2 = B1 or B1+1
P = pow(A, B1, M),
case B2 of
B1 -> (P*P) rem M;
_ -> (P*P*A) rem M
end.
%% inv(A, B) = C | no_inverse
%% computes C such that
%% A*C mod B = 1
%% computes A^-1 mod B
%% examples inv(28, 75) = 67.
%% inv(3533, 11200) = 6597
%% inv(6597, 11200) = 3533
inv(A, B) ->
case solve(A, B) of
{X, Y} ->
if X < 0 -> X + B;
true -> X
end;
_ ->
no_inverse
end.
%% solve(A, B) => {X, Y} | insoluble
%% solve the linear congruence
%% A * X - B * Y = 1
%S tag1
solve(A, B) ->
case catch s(A,B) of
insoluble -> insoluble;
{X, Y} ->
case A * X - B * Y of
1 -> {X, Y};
Other -> error
end
end.
s(A, 0) -> throw(insoluble);
s(A, 1) -> {0, -1};
s(A, -1) -> {0, 1};
s(A, B) ->
K1 = A div B,
K2 = A - K1*B,
{Tmp, X} = s(B, -K2),
{X, K1 * X - Tmp}.
%E tag1
%% converts a string to a base 256 integer
%% converts a base 256 integer to a string
%S tag2
str2int(Str) -> str2int(Str, 0).
str2int([H|T], N) -> str2int(T, N*256+H);
str2int([], N) -> N.
int2str(N) -> int2str(N, []).
int2str(N, L) when N =< 0 -> L;
int2str(N, L) ->
N1 = N div 256,
H = N - N1 * 256,
int2str(N1, [H|L]).
%E tag2
%% greatest common denominator
gcd(A, B) when A < B -> gcd(B, A);
gcd(A, 0) -> A;
gcd(A, B) ->
gcd(B, A rem B).

View File

@@ -1,92 +0,0 @@
-module(primes).
-doc([{author,'Joe Armstrong'},
{title,"Prime number utilities."},
{keywords, [prime, numbers]},
{date,981103}]).
-export([make/1, make_prime/1, is_prime/1]).
-compile(export_all).
%% make a prime with at least K decimal digits
%% Here we use 'Bertrand's postulate, is that for every N > 3,
%% there is a prime P satisfying N < P < 2N - 2
%% This was proved by Tchebychef in 1850 (Erdos improved this proof
%% in 1932)
%S tag4
make_prime(K) when K > 0 ->
new_seed(),
N = make(K),
if N > 3 ->
io:format("Generating a ~w digit prime ",[K]),
MaxTries = N - 3,
P1 = make_prime(MaxTries, N+1),
io:format("~n",[]),
P1;
true ->
make_prime(K)
end.
make_prime(0, _) ->
exit(impossible);
make_prime(K, P) ->
io:format(".",[]),
case is_prime(P) of
true -> P;
false -> make_prime(K-1, P+1)
end.
%E tag4
%% make(N) -> a random integer with N digits.
%S tag1
make(N) -> new_seed(), make(N, 0).
make(0, D) -> D;
make(N, D) ->
make(N-1, D*10 + (random:uniform(10)-1)).
%E tag1
%% Fermat's little theorem says that if
%% N is a prime and if A < N then
%% A^N mod N = A
%S tag3
is_prime(D) ->
new_seed(),
is_prime(D, 100).
is_prime(D, Ntests) ->
N = length(integer_to_list(D)) -1,
is_prime(Ntests, D, N).
is_prime(0, _, _) -> true;
is_prime(Ntest, N, Len) ->
K = random:uniform(Len),
%% A is a random number less than N
A = make(K),
if
A < N ->
case lin:pow(A,N,N) of
A -> is_prime(Ntest-1,N,Len);
_ -> false
end;
true ->
is_prime(Ntest, N, Len)
end.
%E tag3
new_seed() ->
{_,_,X} = erlang:now(),
{H,M,S} = time(),
H1 = H * X rem 32767,
M1 = M * X rem 32767,
S1 = S * X rem 32767,
put(random_seed, {H1,M1,S1}).

View File

@@ -1,56 +0,0 @@
-module(rsa_key).
-export([make_sig/1, make_sig/2]).
make_sig(Who, Len) when Len > 79 ->
{Public, Private} = make_sig(Len),
file:write_file(Who ++ ".pub", term_to_binary(Public)),
file:write_file(Who ++ ".pri", term_to_binary(Private)),
{keyfilecreated,for,Who}.
%% The "book" says ...
%% 1. Bob generates two primes p and q
%% 2. Bob computes n = pq and phi(n) = (p-1)*(q-1)
%% 3. Bob chooses a random b(0 < b < phi(n)) such that
%% gcd(b, phi(n)) = 1
%% 4. Bob computes a = b^(-1) mod phi(n) using the Euclidean algorithm
%% 5. Bob publishes n and b in a directory as his public key.
%S tag1
make_sig(Len) ->
%% generate two <Len> digit prime numbers
P = primes:make_prime(Len),
io:format("P = ~p~n", [P]),
Q = primes:make_prime(Len),
io:format("Q = ~p~n", [Q]),
N = P*Q,
io:format("N = ~p~n", [N]),
Phi = (P-1)*(Q-1),
%% now make B such that B < Phi and gcd(B, Phi) = 1
B = b(Phi),
io:format("Public key (B) = ~p~n", [B]),
A = lin:inv(B, Phi),
io:format("Private key (A) = ~p~n", [A]),
{{B,N},{A,N}}.
b(Phi) ->
io:format("Generating a public key B "),
K = length(integer_to_list(Phi)) - 1,
B = b(1, K, Phi),
io:format("~n", []),
B.
b(Try, K, Phi) ->
io:format("."),
B = primes:make(K),
if
B < Phi ->
case lin:gcd(B, Phi) of
1 -> B;
_ -> b(Try+1, K, Phi)
end;
true ->
b(Try, K, Phi)
end.
%E tag1

View File

@@ -1,2 +0,0 @@
#!/bin/sh
erl -boot /home/joe/erl/example_programs-2.0/examples-2.0/sos -environment `printenv` -load $1

View File

@@ -1,344 +0,0 @@
-module(sos).
-doc([{author,joe},
{title,"Simple OS written entirely in Erlang"},
{keywords, [os]},
{htmldoc, "sos.html"},
{date,981012}]).
-export([main/0, % starts the system
load_module/1, %
log_error/1,
make_server/3,
cast/2,
rpc/2,
change_behaviour/2,
keep_alive/2,
make_global/2,
on_exit/2,
on_halt/1,
stop_system/1,
every/3,
spawn_fun/1,
spawn_link_fun/1,
lookup/2,
map/2,
reverse/1,
read/0,
write/1,
env/1,
make_scripts/0
]).
-export([internal_call/1]).
main() ->
make_server(io,
fun start_io/0, fun handle_io/2),
make_server(code,
const([init,erl_prim_loader]),
fun handle_code/2),
make_server(error_logger,
const(0), fun handle_error_logger/2),
make_server(halt_demon,
const([]), fun handle_halt_demon/2),
make_server(env,
fun start_env/0, fun handle_env/2),
load_module(error_handler),
Mod = get_module_name(),
load_module(Mod),
run(Mod).
run(Mod) ->
Pid = spawn_link(Mod, main, []),
on_exit(Pid, fun(Why) -> stop_system(Why) end).
load_module(Mod) -> rpc(code, {load_module, Mod}).
handle_code({load_module, Mod}, Mods) ->
case member(Mod, Mods) of
true ->
{already_loaded, Mods};
false ->
case primLoad(Mod) of
ok ->
{{ok,Mod}, [Mod|Mods]};
Error ->
{Error, Mods}
end
end.
primLoad(Module) ->
Str = atom_to_list(Module),
case erl_prim_loader:get_file(Str ++ ".jam") of
{ok, Bin, FullName} ->
case erlang:load_module(Module, Bin) of
{module, Module} ->
ok;
{module, _} ->
{error, wrong_module_in_binary};
Other ->
{error, {bad_object_code, Module}}
end;
error ->
{error, {cannot_locate, Module}}
end.
log_error(Error) -> cast(error_logger, {log, Error}).
handle_error_logger({log, Error}, N) ->
erlang:display({error, Error}),
{ok, N+1}.
%S tag4
on_halt(Fun) -> cast(halt_demon,{on_halt,Fun}).
stop_system(Why) -> cast(halt_demon,{stop_system,Why}).
%E tag4
handle_halt_demon({on_halt, Fun}, Funs) ->
{ok, [Fun|Funs]};
handle_halt_demon({stop_system, Why}, Funs) ->
case Why of
normal -> true;
_ -> erlang:display({stopping_system,Why})
end,
map(fun(F) -> F() end, Funs),
erlang:halt(),
{ok, []}.
%S tag5
read() -> rpc(io, read).
write(X) -> rpc(io, {write, X}).
%E tag5
start_io() ->
Port = open_port({fd,0,1}, [eof, binary]),
process_flag(trap_exit, true),
{false, Port}.
handle_io(read, {true, Port}) ->
{eof, {true, Port}};
handle_io(read, {false, Port}) ->
receive
{Port, {data, Bytes}} ->
{{ok, Bytes}, {false, Port}};
{Port, eof} ->
{eof, {true,Port}};
{'EXIT', Port, badsig} ->
handle_io(read, {false, Port});
{'EXIT', Port, Why} ->
{eof, {true, Port}}
end;
handle_io({write,X}, {Flag,Port}) ->
Port ! {self(), {command, X}},
{ok, {Flag, Port}}.
env(Key) -> rpc(env, {lookup, Key}).
handle_env({lookup, Key}, Dict) ->
{lookup(Key, Dict), Dict}.
start_env() ->
Env = case init:get_argument(environment) of
{ok, [L]} ->
L;
error ->
fatal({missing, '-environment ...'})
end,
map(fun split_env/1, Env).
split_env(Str) -> split_env(Str, []).
split_env([$=|T], L) -> {reverse(L), T};
split_env([], L) -> {reverse(L), []};
split_env([H|T], L) -> split_env(T, [H|L]).
make_server(Name, FunD, FunH) ->
make_global(Name,
fun() ->
Data = FunD(),
server_loop(Name, Data, FunH)
end).
server_loop(Name, Data, Fun) ->
receive
{rpc, Pid, Q} ->
case (catch Fun(Q, Data)) of
{'EXIT', Why} ->
Pid ! {Name, exit, Why},
server_loop(Name, Data, Fun);
{Reply, Data1} ->
Pid ! {Name, Reply},
server_loop(Name, Data1, Fun)
end;
{cast, Pid, Q} ->
case (catch Fun(Q, Data)) of
{'EXIT', Why} ->
exit(Pid, Why),
server_loop(Name, Data, Fun);
Data1 ->
server_loop(Name, Data1, Fun)
end;
{eval, Fun1} ->
server_loop(Name, Data, Fun1)
end.
rpc(Name, Q) ->
Name ! {rpc, self(), Q},
receive
{Name, Reply} ->
Reply;
{Name, exit, Why} ->
exit(Why)
end.
cast(Name, Q) ->
Name ! {cast, self(), Q}.
change_behaviour(Name, Fun) ->
Name ! {eval, Fun}.
const(C) -> fun() -> C end.
keep_alive(Name, Fun) ->
Pid = make_global(Name, Fun),
on_exit(Pid,
fun(Exit) -> keep_alive(Name, Fun) end).
make_global(Name, Fun) ->
case whereis(Name) of
undefined ->
Self = self(),
Pid = spawn_fun(fun() ->
make_global(Self,Name,Fun)
end),
receive
{Pid, ack} ->
Pid
end;
Pid ->
Pid
end.
make_global(Pid, Name, Fun) ->
case register(Name, self()) of
{'EXIT', _} ->
Pid ! {self(), ack};
_ ->
Pid ! {self(), ack},
Fun()
end.
spawn_fun({'fun',Mod,Arity,Chksum,Env}) ->
spawn(?MODULE, internal_call,
[[Mod,Arity,Chksum,[],Env]]).
spawn_link_fun({'fun',Mod,Arity,Chksum,Env}) ->
spawn(?MODULE, internal_call,
[[Mod,Arity,Chksum,[],Env]]).
internal_call([Mod|Args]) ->
apply(Mod, module_lambdas, Args).
on_exit(Pid, Fun) ->
spawn_fun(fun() ->
process_flag(trap_exit, true),
link(Pid),
receive
{'EXIT', Pid, Why} ->
Fun(Why)
end
end).
every(Pid, Time, Fun) ->
spawn_fun(fun() ->
process_flag(trap_exit, true),
link(Pid),
every_loop(Pid, Time, Fun)
end).
every_loop(Pid, Time, Fun) ->
receive
{'EXIT', Pid, Why} ->
true
after Time ->
Fun(),
every_loop(Pid, Time, Fun)
end.
get_module_name() ->
case init:get_argument(load) of
{ok, [[Arg]]} ->
module_name(Arg);
error ->
fatal({missing, '-load Mod'})
end.
%S tag7
lookup(Key, [{Key,Val}|_]) -> {found, Val};
lookup(Key, [_|T]) -> lookup(Key, T);
lookup(Key, []) -> not_found.
member(X, [X|_]) -> true;
member(H, [_|T]) -> member(H, T);
member(_, []) -> false.
map(F, [H|T]) -> [F(H)|map(F, T)];
map(F, []) -> [].
reverse(X) -> reverse(X, []).
reverse([H|T], L) -> reverse(T, [H|L]);
reverse([], L) -> L.
module_name(Str) ->
case (catch list_to_atom(Str)) of
{'EXIT', _} ->
log_error({bad_module_name,Str}),
stop_system(bad_start_module);
Mod -> Mod
end.
%E tag7
fatal(Term) ->
log_error({fatal, Term}),
stop_system({fatal, Term}).
%S tag8
make_scripts() ->
{ok, Cwd} = file:get_cwd(),
Script =
{script,{"sos","1.0"},
[{preLoaded,[init,erl_prim_loader]},
{progress,preloaded},
{path,
[".",
Cwd,
"$ROOT/lib/" ++ lib_location(kernel) ++ "/ebin",
"$ROOT/lib/" ++ lib_location(stdlib) ++ "/ebin"]},
{primLoad,
[erl_open_port,
erlang,
error_handler,
sos
]},
{kernel_load_completed},
{progress,kernel_load_completed},
{progress,started},
{apply,{sos,main,[]}}
]},
file:write_file("sos.boot", term_to_binary(Script)),
{ok, Stream} = file:open("sos", write),
io:format(Stream, "#!/bin/sh~nerl -boot ~s/sos "
" -environment `printenv` -load $1~n",
[Cwd]),
file:close(Stream),
unix:cmd("chmod a+x sos"),
true.
lib_location(Lib) ->
filename:basename(code:lib_dir(Lib)).
%E tag8

View File

@@ -1,7 +0,0 @@
-module(sos_err1).
-doc(none).
-export([main/0]).
main() ->
listsforeaack:abc(123),
sos:write("Hello world\n").

View File

@@ -1,7 +0,0 @@
-module(sos_err2).
-doc(none).
-export([main/0]).
main() ->
lists:abc(123),
sos:write("Hello world\n").

View File

@@ -1,6 +0,0 @@
-module(sos_test1).
-doc(none).
-export([main/0]).
main() ->
sos:write("Hello world\n").

View File

@@ -1,7 +0,0 @@
-module(sos_test2).
-doc(none).
-export([main/0]).
main() ->
X = lists:reverse("Hellow world"),
sos:write([X,"\n"]).

View File

@@ -1,16 +0,0 @@
-module(sos_test3).
-doc(none).
-export([main/0]).
-import(sos, [read/0, write/1]).
main() ->
loop().
loop() ->
case read() of
eof ->
true;
{ok, X} ->
write([X]),
loop()
end.

View File

@@ -1,8 +0,0 @@
-module(sos_test4).
-doc(none).
-export([main/0]).
main() ->
sos:write("I will crash now\n"),
1 = 2,
sos:write("This line will not be printed\n").

View File

@@ -1,8 +0,0 @@
Suffix .erl.jam ->
c:c($>).
Suffix .tex.dvi ->
unix:cmd("latex $>.tex").
Suffix .ehtml.html ->
ehtml:file("$>").

View File

@@ -1,17 +0,0 @@
%% This is a macro
OBJS = a.jam, b.jam.
OBJS += ,c.jam.
include("suffix_rules").
all when a.dvi $(OBJS).
a.dvi when a.tex ->
io:format("touching a.dvi~n"),
unix:cmd("touch a.dvi"),
io:format("done~n").

View File

@@ -1,13 +0,0 @@
%% This is a macro
OBJS = abc.jam, a.jam, b.jam.
include("$(MAKEDIR)/suffix_rules").
all when $(OBJS) a.dvi.
a.dvi when a.tex ->
unix:cmd("touch a.dvi").

View File

@@ -1,52 +0,0 @@
%%
%% Make the tk library
%%
Jamdir=../ebin.
CC = gcc.
tk when $(Jamdir)/tk.jam, $(Jamdir)/tkfocus.jam,
tkbutton.jam, tkentry.jam,
tkscrlbar.jam, tkdialog.jam, tklib.jam ->
X = 12,
Y = 14,
tk:stop(X, Y, X+Y).
$(Jamdir)/tk.jam when tk.erl, tk.hrl ->
c:c(tk, [{outdir, "$(Jamdir)"}]).
$(Jamdir)/tkfocus.jam when tkfocus.erl, tk.hrl ->
c:c(tkfocus, [{outdir, "$(Jamdir)"}]).
$(Jamdir)/tkbutton.jam when tkbutton.erl, tk.hrl ->
c:c(tkbutton, [{outdir, "$(Jamdir)"}]).
$(Jamdir)/tkentry.jam when tkentry.erl, tk.hrl ->
c:c(tkentry, [{outdir, "$(Jamdir)"}]).
tkscrlbar.jam when tkscrlbar.erl, tk.hrl ->
c:c(tkscrlbar, [{outdir, "$(Jamdir)"}]).
tkdialog.jam when tkdialog.erl ->
c:c(tkdialog, [{outdir, "$(Jamdir)"}]).
tklib.jam when tklib.erl ->
io:format("compiling: $@~n"),
c:c(tklib, [{outdir, "$(Jamdir)"}]).
foo.o when foo.c ->
unix:cmd("$(CC) -o $@ -c foo.c").
foo when bar ->
X = case Jamdir of
"../ebin" -> 1;
".." -> 2;
"." -> 3
end,
io:format("this = ~w", [X]).

View File

@@ -1,7 +0,0 @@
all when a.jam ->
p,q,r.
all -> a,b,c.
all,b,c when a,b,c.

View File

@@ -1,22 +0,0 @@
\begin{titlepage}
\begin{center}
\vspace*{1.0cm}
{\Huge\bf
The Erlang Cookbook\\
}
\vskip 1.0 true cm
\vskip 3.0 true cm
{\large\bf
Joe Armstrong\\
}
\vskip 1.0 true cm
\end{center}
\eject
\end{titlepage}

View File

@@ -1,66 +0,0 @@
-module(topological_sort).
%% Copyright (C) 1998, Ericsson Computer Science Laboratory
-doc([{author,'Joe Armstrong'},
{title,"Topological sort of a partial order."},
{keywords, [topological,sort,partial,order]},
{date,981102}]).
-export([sort/1, test/0]).
-import(lists, [map/2, member/2, filter/2]).
%% -type([{X, X}]) -> {ok, [{X,Y}]} | {cycle, [{X,Y}]}
%% topological_sort:pairs(L)
%% A partial order on the set S is a set of pairs {Xi,Xj} such that
%% some relation between Xi and Xj is obeyed.
%% A topological sort of a partial order is a sequence of elements
%% [X1, X2, X3 ...] such that if whenever {Xi, Xj} is in the partial
%% order i < j
test() ->
Pairs = [{1,2},{2,4},{4,6},{2,10},{4,8},{6,3},{1,3},
{3,5},{5,8},{7,5},{7,9},{9,4},{9,10}],
sort(Pairs).
%% [7,1,9,2,4,6,3,5,8,10]
%S tag1
sort(Pairs) ->
iterate(Pairs, [], all(Pairs)).
iterate([], L, All) ->
{ok, remove_duplicates(L ++ subtract(All, L))};
iterate(Pairs, L, All) ->
case subtract(lhs(Pairs), rhs(Pairs)) of
[] ->
{cycle, Pairs};
Lhs ->
iterate(remove_pairs(Lhs, Pairs), L ++ Lhs, All)
end.
all(L) -> lhs(L) ++ rhs(L).
lhs(L) -> map(fun({X,_}) -> X end, L).
rhs(L) -> map(fun({_,Y}) -> Y end, L).
%% subtract(L1, L2) -> all the elements in L1 which are not in L2
subtract(L1, L2) -> filter(fun(X) -> not member(X, L2) end, L1).
remove_duplicates([H|T]) ->
case member(H, T) of
true -> remove_duplicates(T);
false -> [H|remove_duplicates(T)]
end;
remove_duplicates([]) ->
[].
%% remove_pairs(L1, L2) -> L2' L1 = [X] L2 = [{X,Y}]
%% removes all pairs from L2 where the first element
%% of each pair is a member of L1
remove_pairs(L1, L2) -> filter(fun({X,Y}) -> not member(X, L1) end, L2).
%E tag1

View File

@@ -1,39 +0,0 @@
-module(transitive).
%% Copyright (C) 1997, Ericsson Telecom AB
-doc([{author,'Joe Armstrong'},
{title,"Transitive closure of a graph."},
{keywords, [transitive,closure]},
{date,981102}]).
%% warning slow on big graphs
-export([closure/2]).
%S tag1
closure(RootSet, Pairs) ->
closure_list(RootSet, Pairs, RootSet).
closure(Start, [], L) ->
L;
closure(Start, Pairs, Reachable) ->
{Next, Rest} = next(Start, Pairs),
closure_list(Next, Rest, Next ++ Reachable).
closure_list([], Pairs, Reachable) ->
Reachable;
closure_list([H|T], Pairs, Reachable) ->
Reachable1 = closure(H, Pairs, Reachable),
closure_list(T, Pairs, Reachable1).
next(Start, Pairs) ->
next(Start, Pairs, [], []).
next(Start, [], Reach, NoReach) ->
{Reach, NoReach};
next(Start, [{Start,Next}|T], Reach, NoReach) ->
next(Start, T, [Next|Reach], NoReach);
next(Start, [H|T], Reach, NoReach) ->
next(Start, T, Reach, [H|NoReach]).
%E tag1

View File

@@ -1,3 +0,0 @@
{"joe", "zapme"}.
{"ftp","ftp"}.
{"jane","hospan"}.

View File

@@ -1,7 +0,0 @@
block data
integer nmax
parameter (nmax=20)
real v(nmax), alpha, beta
common /vector/v,alpha,beta
data v/20*100.0/, alpha/3.14/, beta/2.71/
end

View File

@@ -1,150 +0,0 @@
c<html>
c<body>
c<pre>
module constants
integer, parameter :: np=2000, dbl=selected_real_kind(14,100)
real(dbl) :: g=9.807,dtmin=.001
end module constants
c
program fall
use constants
implicit none
c
c Program to calculate the dynamics of a falling body
c
c John Mahaffy 4/15/95
c
c Arrays:
c v - velocity at each time integration step
c z - height at each time integration step
c t - time for each corresponding v and z
c zreal - Actual height at time t(i) for comparison with computed z
c
c In this program, I am using allocatate just to save space in the
c executable program file (a.out). No attempt is made to estimate a size.
c Module "constants" communicates between subroutines.
c
c<a name="alable"><font color="FF0000">
real(dbl), allocatable :: v(:),z(:),t(:), zreal(:)
c</font></a>
real(dbl) dt
integer nsteps
c<a name="all"><font color="FF0000">
allocate (v(np),z(np),t(np),zreal(np))
c</font></a>
call input(z,dt)
call odesolve(v,z,t,dt,nsteps)
call realans(t,z,nsteps,zreal)
call output (t,z,zreal,v,nsteps)
stop
end
c
subroutine input (z,dt)
use constants
implicit none
c
c Obtain user input for initial height and time step
c
c John Mahaffy 4/15/95
c
c Output Arguments:
c z(1) - initial height
c dt - integration time step
c
real(dbl) z(*),dt
c
write(6,'(a)',advance='no') ' Initial height (meters): '
read *, z(1)
write(6,'(a)',advance='no') 'Time step size (seconds): '
read *, dt
if(dt.le.0.) dt=dtmin
return
end
c
subroutine odesolve(v,z,t,dt,nsteps)
use constants
c
c Solve the Ordinary Differential Equation of motion for the body
c
c John Mahaffy 4/15/95
c
c Arguments:
c Input
c dt - timestep size
c Output:
c v - velocity
c z - height
c t - time
c nsteps - last step in the integration
c
real (dbl) v(*),z(*),t(*),dt
integer i, nsteps
c
c Solve the equation for a falling body
c
c d v d z
c --- = - g --- = v
c d t d t
c
c Set remaining initial conditions:
c
t(1)=0.
v(1)=0.
c
c Now loop through time steps until z goes negative or we run out of space
c
do 100 i=2,np
v(i)= v(i-1)-dt*g
z(i)= z(i-1)+dt*.5*(v(i)+v(i-1))
t(i)=t(i-1)+dt
if(z(i).lt.0.) go to 200
c<a name="con"><font color="FF0000">
100 continue
c</font></a>
write(6,*) 'Ran out of space to continue integration'
write(6,*) ' Last height was ',z(np),' meters'
i=np
200 nsteps=i
c return
end
c
subroutine realans(t,z,nsteps,zreal)
use constants
c
c Get the values of the analytic solution to the differential equation
c for each time point to check the numerical accuracy.
c
c John Mahaffy 4/15/95
c
real(dbl) t(*),z(*),zreal(*)
integer i,nsteps
c
do 10 i=1,nsteps
10 zreal(i)=z(1)-.5*g*t(i)**2
return
end
c
subroutine output(t,z,zreal,v,nsteps)
use constants, only : dbl
implicit none
c
c Outputs the full results of the time integration
c
c John Mahaffy 4/15/95
c
real(dbl) v(*),z(*),t(*), zreal(*)
integer nsteps,i
print *, 'Results are in fall.output'
open (11,file='fall.output')
write(11,2000)
do 300 i=1,nsteps
write(11,2001) t(i),v(i),z(i),zreal(i)
300 continue
2000 format (33x,'Computed',8x,'Actual',/,
& 6x,'Time',9x,'Velocity', 8x,'Height',8x,'Height')
2001 format (1x,1p,4e15.7)
return
end
c</pre>
c</body>
c</html>

View File

@@ -1,55 +0,0 @@
program htcoef
c
c John Mahaffy, Penn State University, CmpSc 201 Example
c 1/26/96
c
implicit none
real k,D,Pr,h,Nulam,Nuturb
real Re1,Re2,Re3,Re4
c
c Calculate an approximation for heat transfer coefficients
c in a 1 inch pipe for several different Reynolds numbers
c
c An example of why you should learn to use subprograms
c
c h - heat transfer coefficient ( w/m**2/K)'
c Nulam - laminar Nusselt number
c Nuturb - Turbulent Nusselt number (Dittus-Boelter correlation)
c k - conductivity ( w/m/K)'
c D - hydraulic diameter (m)
c Re - Reynolds number
c Pr - Prandl number
c
data k,D,Pr/0.617,0.0254,1.0/, Nulam/4.0/
c
c Each of the following blocks assigns a Reynolds number, calculates
c an associated Turbulent Nusselt number and calculates the heat
c transfer coefficient based on the maximum of Turbulent and Laminar
c Nusselt Numbers
c
Re1=10.
Nuturb=0.023*Re1**0.8*Pr**0.4
h=k/D*max(Nulam,Nuturb)
print *, 'For Reynolds Number = ',Re1
print *, 'Heat Transfer Coefficient is ',h,' w/m**2/K'
c
Re2=100.
Nuturb=0.023*Re2**0.8*Pr**0.4
h=k/D*max(Nulam,Nuturb)
print *, 'For Reynolds Number = ',Re2
print *, 'Heat Transfer Coefficient is ',h,' w/m**2/K'
c
Re3=1000.
Nuturb=0.023*Re3**0.8*Pr**0.4
h=k/D*max(Nulam,Nuturb)
print *, 'For Reynolds Number = ',Re3
print *, 'Heat Transfer Coefficient is ',h,' w/m**2/K'
c
Re4=10000.
Nuturb=0.023*Re4**0.8*Pr**0.4
h=k/D*max(Nulam,Nuturb)
print *, 'For Reynolds Number = ',Re4
print *, 'Heat Transfer Coefficient is ',h,' w/m**2/K'
c
stop
end

View File

@@ -1,22 +0,0 @@
subroutine linint(x,y)
c
c Given a value of x return a value of y based on interpolation
c within a table of y values (ytab) evaluated at evenly spaced
c x points between xmin and xmax.
c
c John Mahaffy 2/12/95
c
real ytab(11)
parameter (xmin=300.,dx=100.,xmax=xmin+10.*dx,rdx=1./dx)
data ytab/1.0,2.1,3.2,4.4,5.7,7.1,8.6,10.2,11.9,13.7,15.8/
if(x.ge.xmin.and.x.le.xmax) then
i1= int((x-xmin)*rdx)+1
x1=xmin+(i1-1)*dx
wx=(x-x1)*rdx
y=(1-wx)*ytab(i1)+wx*ytab(i1+1)
else
write(6,*) 'x = ', x, ' is out of table range'
stop
endif
return
end

View File

@@ -1,209 +0,0 @@
c<html>
c<head><title>plot2.f</title></head>
c<body>
c<pre>
program plotit
c
c Program to provide plots of Sin(x)
c Ascii Character plots go to terminal and file 'pplot.out'
c
c John Mahaffy 2/1/95
c
implicit none
c
c The following line tells Fortran that "func" is a function or subroutine
c and not a variable
c
c<a name="ex"><font color="FF0000">
external func
c</font></a>
c
c The next line is necessary to pass the location of the intrinsic sin
c function as an argument to a subprogram
c
c<a name="intrinsic"><font color="FF0000">
intrinsic sin
c</font></a>
c
call pplot(func,0.,6.)
print *, 'Hit the Enter key to continue'
c<a name="pause"><font color="FF0000">
pause
c</font></a>
call gnuplot('x','y','sin(x)',func,0.0,6.0)
call gnuplot('x','y','Intrinsic sin(x)',sin,0.0,6.0)
stop
end
subroutine pplot(f,xmin,xmax)
c
c Generate ASCII character plot to screen and file 'pplot.out'
c
implicit none
character line*72
real x, f , xmin , xmax
integer ip,i,imax
c
c The following line tells Fortran that f is a function or subroutine
c and not a variable
c
external f
c
c INPUT Arguments
c
c f - function to be ploted
c xmin - minimum x value
c xmax - maximum x value
c
c OTHER key variables
c
c line - Character string loaded with a line of output
c ip - Position in line for a function value
c
open (11,file='pplot.out')
c
c Label values of the y axis
c
line=' '
line(14:15)='-1'
line(65:65)='1'
write(*,*) line
write(11,*) line
line=' '
write(line(10:13),'(f4.1)') xmin
c
c Draw the y axis
c
line(15:40)='+----+----+----+----+----+'
line(41:65)=line(16:40)
c
c Plot the value at x=0
c
ip= nint(25*f(0.0))+40
line(ip:ip)='*'
write(*,*) line
write(11,*) line
line=' '
imax=nint((xmax-xmin)*10)
c
c Limit output
c
imax=min(1000,imax)
c
c Loop through and plot points for other x values
c
do 50 i=1,imax
x=.1*i
ip=nint(25*f(x))+40
c
if(mod(i,10).eq.0) then
write(line(10:13),'(f4.1)') x
line(40:40)='+'
c<a name="else"><font color="FF0000">
else
c</font></a>
line(10:13)=' '
line(40:40)='|'
endif
line(ip:ip)='*'
write(*,*) line
write(11,*) line
50 line(ip:ip)=' '
c<a name="close"><font color="FF0000">
close (11)
c</font></a>
return
end
subroutine gnuplot(xlabel,ylabel,title,f,xmin,xmax)
c
c Ship data to the public domain program "gnuplot" for plotting
c
implicit none
character line*72,sq*1
real x,f,xmin,xmax,fx
character*(*) xlabel,ylabel,title
integer i,imax,lc
external f
data sq/''''/
c
c INPUT Arguments
c
c f - function to be ploted
c xmin - minimum x value
c xmax - maximum x value
c xlabel - Contains a label for the x-axis
c ylabel - Contains a label for the y-axis
c title - Contains a title for the plot
c
c OTHER key variables
c
c line - Contains a line of character data
c
c Drive a separate true graphics program (gnuplot)
c
c First set up the command file for gnuplot
c Run gnuplot interactively and use the "help" command to learn more
c about what I am doing.
c
open (12,file='gnuxy')
c
c UnComment the next line if you are on a NCSA/BYU Telnet Session
c
c write(12,*) 'set terminal tek40xx'
c
write(12,*) 'set data style lines'
c <a name=1><font color=FF0000>
lc=len(xlabel)
c </font>
line='set xlabel '''//xlabel(1:lc)//sq
write(12,*)line
c
c You don't really need to calculate the character variable length
c here. The following works just fine because of the character*(*)
c
line='set ylabel '''//ylabel//sq
write(12,*)line
line='set title '''//title//sq
write(12,*)line
write(12,*)'set nokey'
write(12,2000) xmin,xmax
2000 format('set xrange [',f3.0,':',f3.0,']')
write(12,*) 'plot ''dataxy'' using 1:2'
write(12,*) 'pause 10'
close(12)
c
c Generate x-y pairs for the graph
c
open (12,file='dataxy')
imax=nint((xmax-xmin)*10)
c
c Limit output
c
imax=min(1000,imax)
c
do 100 i=0,imax
x=.1*i
fx=f(x)
write(12,*) x,fx
100 continue
close(12)
c
c Tell the system to run the program gnuplot
c This call works on either IBM RS6000 or Sun, but is not part of
c the Fortran standard.
c Comment out the line if you aren't at a terminal with graphics
c
call system('gnuplot gnuxy')
c<a name="10"><font color="FF0000">
return
c</a></font>
end
c<a name="fun"><font color="FF0000">
real function func(x)
c</font></a>
func=sin(x)
return
end
c</pre>
c</body>
c</html>

View File

@@ -1,73 +0,0 @@
function thcl(temp)
c
c function thcl evaluates the freon liquid thermal conductivity
c as a function of liquid enthalpy
c
c liquid temperature temp in (j/kg)
c thermal conductivity thcl in (w/m/k)
c
c
c
dimension tabl(4,26)
save ilast
data ilast/15/,ntab/26/
data tabl/
& 1.99826700E+02, 1.15267000E-01,-3.03660304E-04, 6.96601393E-07,
& 2.10937800E+02, 1.11979000E-01,-2.88180288E-04, 6.96601393E-07,
& 2.22048900E+02, 1.08863000E-01,-2.72700273E-04,-6.88501377E-07,
& 2.33160000E+02, 1.05748000E-01,-2.88000288E-04, 6.88501377E-07,
& 2.44271100E+02, 1.02633000E-01,-2.72700273E-04,-6.96601393E-07,
& 2.55382200E+02, 9.95170000E-02,-2.88180288E-04, 7.04701409E-07,
& 2.66493300E+02, 9.64020000E-02,-2.72520273E-04,-7.04701409E-07,
& 2.77604400E+02, 9.32870000E-02,-2.88180288E-04, 6.96822277E-07,
& 2.88715600E+02, 9.01710000E-02,-2.72695225E-04,-6.88955687E-07,
& 2.99826700E+02, 8.70560000E-02,-2.88005336E-04, 6.88955687E-07,
& 3.10937800E+02, 8.39410000E-02,-2.72695225E-04,-6.97055703E-07,
& 3.22048900E+02, 8.08250000E-02,-2.88185336E-04, 7.05155719E-07,
& 3.33160000E+02, 7.77100000E-02,-2.72515225E-04,-7.05155719E-07,
& 3.44271100E+02, 7.45950000E-02,-2.88185336E-04, 6.97055703E-07,
& 3.55382200E+02, 7.14790000E-02,-2.72695225E-04,-6.88955687E-07,
& 3.66493300E+02, 6.83640000E-02,-2.88005336E-04, 6.88955687E-07,
& 3.77604400E+02, 6.52490000E-02,-2.72695225E-04,-6.96822277E-07,
& 3.88715600E+02, 6.21330000E-02,-2.88180288E-04, 7.04701409E-07,
& 3.99826700E+02, 5.90180000E-02,-2.72520273E-04,-7.04701409E-07,
& 4.10937800E+02, 5.59030000E-02,-2.88180288E-04, 6.96601393E-07,
& 4.22048900E+02, 5.27870000E-02,-2.72700273E-04,-4.89240978E-06,
& 4.33160000E+02, 4.91530000E-02,-3.81420381E-04, 6.80401361E-07,
& 4.44271100E+02, 4.49990000E-02,-3.66300366E-04,-6.28561257E-06,
& 4.55382200E+02, 4.01530000E-02,-5.05980506E-04,-2.45592491E-05,
& 4.66493300E+02, 3.14990000E-02,-1.05174105E-03,-2.18924207E-04,
& 4.70937800E+02, 2.25000000E-02, 0.00000000E+00, 0.00000000E+00/
x=temp
c Start the search from the last point of table use index
c
if (x.le.tabl(1,ilast+1)) then
c
c Search down the table from point of last use
c
do 20 i1=ilast,1,-1
if(x.ge.tabl(1,i1)) go to 60
20 continue
c write(6,*) 'x = ', x, ' is below the table range'
i1=1
go to 60
else
c
c Search up the table from point of last use
c
do 40 i1=ilast+1,ntab-1
if(x.le.tabl(1,i1+1)) go to 60
40 continue
c write(6,*) 'x = ', x, ' is above the table range'
i1=ntab-1
go to 60
endif
c
c Bounding points found, interpolate
c
60 dx=(x-tabl(1,i1))
thcl=tabl(2,i1)+tabl(3,i1)*dx+tabl(4,i1)*dx**2
ilast=i1
120 continue
return
end

View File

@@ -1,46 +0,0 @@
// This file is part of the Java Compiler Kit (JKit)
//
// The Java Compiler Kit is free software; you can
// redistribute it and/or modify it under the terms of the
// GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your
// option) any later version.
//
// The Java Compiler Kit is distributed in the hope
// that it will be useful, but WITHOUT ANY WARRANTY; without
// even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public
// License along with the Java Compiler Kit; if not,
// write to the Free Software Foundation, Inc., 59 Temple Place,
// Suite 330, Boston, MA 02111-1307 USA
//
// (C) David James Pearce, 2009.
package jkit.jil.dfa;
public interface FlowSet {
/**
* FlowSets must be cloneable to facilitate multiple flows of execution
* from conditionals
*
* @return A Clone of the current FlowSet
*/
public Object clone();
/**
* Computes the least upper bound of this flowset and that provided. <b>NOTE</b>
* the join operation has a subtle, yet important, requirement. If the
* result of the join must be equivalent to *this* flowset, then it must be
* the *same* flowset.
*
* @param s
* Another FlowSet to join with this
* @return true if this FlowSet has changed due to the computation, false
* otherwise
*/
public FlowSet join(FlowSet s);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,40 +0,0 @@
import javax.swing.ImageIcon;
/**
* A Ship square represents a square that contains a battle ship, but has not
* yet been bombed. Ship Squares can be either visible or invisible (depending
* on which side they are).
*
* @author djp
*/
public class ShipSquare extends GridSquare {
private BattleShip ship;
private Type type;
public enum Type {
VERTICAL_TOP_END,
HORIZONTAL_MIDDLE
};
/**
* Construct a ShipSquare representing part of a battle ship (either a
* middle or end piece).
*
*/
public ShipSquare(Type type, BattleShip ship) {
this.type = type;
this.ship = ship;
}
/**
* Get the ship that this square is part of.
* @return
*/
public BattleShip getShip() { return ship; }
/**
* Determine what part of the ship this piece represents.
* @return
*/
public Type getType() { return type; }
}

View File

@@ -1,16 +0,0 @@
$(function(){
window.Todo = Backbone.Model.extend({
defaults: function() {
return {
done: false,
order: Todos.nextOrder()
};
},
// Toggle the `done` state of this todo item.
toggle: function() {
this.save({done: !this.get("done")});
}
});
});

View File

@@ -1,83 +0,0 @@
// base class
var Animal = Class.create({
initialize: function(name) {
this.name = name;
},
name: "",
eat: function() {
return this.say("Yum!");
},
say: function(message) {
return this.name + ": " + message;
}
});
// subclass that augments a method
var Cat = Class.create(Animal, {
eat: function($super, food) {
if (food instanceof Mouse) return $super();
else return this.say("Yuk! I only eat mice.");
}
});
// empty subclass
var Mouse = Class.create(Animal, {});
//mixins
var Sellable = {
getValue: function(pricePerKilo) {
return this.weight * pricePerKilo;
},
inspect: function() {
return '#<Sellable: #{weight}kg>'.interpolate(this);
}
};
var Reproduceable = {
reproduce: function(partner) {
if (partner.constructor != this.constructor || partner.sex == this.sex)
return null;
var weight = this.weight / 10, sex = Math.random(1).round() ? 'male' : 'female';
return new this.constructor('baby', weight, sex);
}
};
// base class with mixin
var Plant = Class.create(Sellable, {
initialize: function(name, weight) {
this.name = name;
this.weight = weight;
},
inspect: function() {
return '#<Plant: #{name}>'.interpolate(this);
}
});
// subclass with mixin
var Dog = Class.create(Animal, Reproduceable, {
initialize: function($super, name, weight, sex) {
this.weight = weight;
this.sex = sex;
$super(name);
}
});
// subclass with mixins
var Ox = Class.create(Animal, Sellable, Reproduceable, {
initialize: function($super, name, weight, sex) {
this.weight = weight;
this.sex = sex;
$super(name);
},
eat: function(food) {
if (food instanceof Plant)
this.weight += food.weight;
},
inspect: function() {
return '#<Ox: #{name}>'.interpolate(this);
}
});

View File

@@ -1,107 +0,0 @@
/*
* jQuery UI Progressbar @VERSION
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Progressbar
*
* Depends:
* jquery.ui.core.js
* jquery.ui.widget.js
*/
(function( $, undefined ) {
$.widget( "ui.progressbar", {
options: {
value: 0,
max: 100
},
min: 0,
_create: function() {
this.element
.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
.attr({
role: "progressbar",
"aria-valuemin": this.min,
"aria-valuemax": this.options.max,
"aria-valuenow": this._value()
});
this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
.appendTo( this.element );
this.oldValue = this._value();
this._refreshValue();
},
_destroy: function() {
this.element
.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
.removeAttr( "role" )
.removeAttr( "aria-valuemin" )
.removeAttr( "aria-valuemax" )
.removeAttr( "aria-valuenow" );
this.valueDiv.remove();
},
value: function( newValue ) {
if ( newValue === undefined ) {
return this._value();
}
this._setOption( "value", newValue );
return this;
},
_setOption: function( key, value ) {
if ( key === "value" ) {
this.options.value = value;
this._refreshValue();
if ( this._value() === this.options.max ) {
this._trigger( "complete" );
}
}
this._super( "_setOption", key, value );
},
_value: function() {
var val = this.options.value;
// normalize invalid value
if ( typeof val !== "number" ) {
val = 0;
}
return Math.min( this.options.max, Math.max( this.min, val ) );
},
_percentage: function() {
return 100 * this._value() / this.options.max;
},
_refreshValue: function() {
var value = this.value();
var percentage = this._percentage();
if ( this.oldValue !== value ) {
this.oldValue = value;
this._trigger( "change" );
}
this.valueDiv
.toggle( value > this.min )
.toggleClass( "ui-corner-right", value === this.options.max )
.width( percentage.toFixed(0) + "%" );
this.element.attr( "aria-valuenow", value );
}
});
$.extend( $.ui.progressbar, {
version: "@VERSION"
});
})( jQuery );

View File

@@ -1,27 +0,0 @@
/* Object Literal Notation */
var objectLiteral = {
str: '1',
func: function() { return 1; }
};
/* Module Pattern 1 */
var module = (function(){
var private = 1;
return {
method: function() { private++; }
};
})();
/* Module Pattern 2 */
var module2 = {};
(function(context){
var private = 1;
context.method = function() { private++; }
})(module2);
/* Module Pattern 3 */
var module3 = {};
(function(){
var private = 1;
this.method = function() { private++; }
}).apply(module3);

View File

@@ -1,42 +0,0 @@
// This example is from the book _JavaScript: The Definitive Guide_.
// Written by David Flanagan. Copyright (c) 1996 O'Reilly & Associates.
// This example is provided WITHOUT WARRANTY either expressed or implied.
// You may study, use, modify, and distribute it for any purpose.
function Circle(radius) { // the constructor defines the class itself
// r is an instance variable; defined and initialized in the constructor
this.r = radius;
}
// Circle.PI is a class variable--it is a property of the constructor function
Circle.PI = 3.14159;
// Here is a function that computes a circle area.
function Circle_area() { return Circle.PI * this.r * this.r; }
// Here we make the function into an instance method by assigning it
// to the prototype object of the constructor. Remember that we have to
// create and discard one object before the prototype object exists
new Circle(0);
Circle.prototype.area = Circle_area;
// Here's another function. It takes two circle objects are arguments and
// returns the one that is larger (has the larger radius).
function Circle_max(a,b) {
if (a.r > b.r) return a;
else return b;
}
// Since this function compares two circle objects, it doesn't make sense as
// an instance method operating on a single circle object. But we don't want
// it to be a stand-alone function either, so we make it into a class method
// by assigning it to the constructor function:
Circle.max = Circle_max;
// Here is some code that uses each of these fields:
c = new Circle(1.0); // create an instance of the Circle class
c.r = 2.2; // set the r instance variable
a = c.area(); // invoke the area() instance method
x = Math.exp(Circle.PI); // use the PI class variable in our own computation.
d = new Circle(1.2); // create another Circle instance
bigger = Circle.max(c,d); // use the max() class method.

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +0,0 @@
var app = {
foo: function(){},
bar: function(){}
}
var dsads = {
fdfsd: function(){},
dsadas: function(){}
}

View File

@@ -1,597 +0,0 @@
/* Test file for C++ language.
* Attempt to include as many aspects of the C++ language as possible.
* Do not include things tested in test.c since that shares the
* same language.
*
* $Id: test.cpp,v 1.22 2008/05/17 20:12:55 zappo Exp $
*
*/
/* An include test */
#include <stdio.h>
#include <cmath>
#include "c++-test.hh"
#include <c++-test.hh>
double var1 = 1.2;
int simple1(int a) {
}
struct foo1 {
int test;
};
struct foo2 : public foo1 {
const int foo21(int a, int b);
const int foo22(int a, int b) { return 1 }
};
/* Classes */
class class1 {
private:
int var11;
struct foo1 var12;
public:
int p_var11;
struct foo p_var12;
};
class i_class1 : public class1 {
private:
int var11;
struct foo var12;
public:
int p_var11;
struct foo p_var12;
};
class class2 {
private:
int var21;
struct foo var22;
public:
int p_var21;
struct foo p_var22;
};
class i_class2 : public class1, public class2 {
private:
int var21;
struct foo var22;
protected:
int pt_var21;
public:
int p_var21;
struct foo p_var22;
};
class class3 {
/* A class with strange things in it */
public:
class3(); /* A constructor */
enum embedded_foo_enum {
a, b, c
} embed1;
struct embedded_bar_struct {
int a;
int b;
} embed2;
class embedded_baz_class {
embedded_baz_class();
~embedded_baz_class();
} embed3;
~class3(); /* destructor */
/* Methods */
int method_for_class3(int a, char b);
int inline_method(int c) { return c; }
/* Operators */
class3& operator^= (const class3& something);
/* Funny declmods */
const class3 * const method_const_ptr_ptr(const int * const argconst) const = 0;
};
class3::class3()
{
/* Constructor outside the definition. */
}
int class3::method_for_class3(int a, char b)
{
}
int class3::method1_for_class3( int a, int &b)
{
int cvariablename;
class3 fooy[];
class3 moose = new class3;
// Complktion testing line should find external members.
a = fooy[1].me ;
b = cv ;
if (fooy.emb) {
simple1(c);
}
cos(10);
abs(10);
return 1;
}
char class3::method2_for_class3( int a, int b) throw ( exception1 )
{
return 'a';
}
void *class3::method3_for_class3( int a, int b) throw ( exception1, exception2 )
{
int q = a;
return "Moose";
}
void *class3::method31_for_class3( int a, int b) throw ( )
{
int q = a;
return "Moose";
}
void *class3::method4_for_class3( int a, int b) reentrant
{
class3 ct;
ct.method5_for_class3(1,a);
pritf();
}
/*
* A method on class3.
*/
void *class3::method5_for_class3( int a, int b) const
{
}
/*
* Namespace parsing tests
*/
namespace NS {
class class_in_namespace {
int equiv(const NS::class_in_namespace *) const;
};
}
int NS::class_in_namespace::equiv(const NS::class_in_namespace *cin) const
{
return 0;
}
// Stuff Klaus found.
// Inheritance w/out a specifying for public.
class class4 : class1 {
// Pure virtual methods.
void virtual print () const = 0;
public:
// The whacky constructor type
class4()
try : class1(args)
{
// constructor body
}
catch ()
{
}
};
class class5 : public virtual class4 {
// Virtual inheritance
};
class class6 : class1 {
// Mutable
mutable int i;
};
/* Namespaces */
namespace namespace1 {
void ns_method1() { }
class n_class1 {
public:
void method11(int a) { }
};
/* This shouldn't parse due to missing semicolon. */
class _n_class2 : public n_class1 {
void n_c2_method1(int a, int b) { }
};
// Macros in the namespace
#define NSMACRO 1
// Template in the namespace
template<class T> T nsti1(const Foo& foo);
template<> int nsti1<int>(const Foo& foo);
}
namespace namespace2 {
using namespace1::n_class1;
}
/* Initializers */
void tinitializers1(): inita1(False),
inita2(False)
{
inita1= 1;
}
/* How about Extern C type things. */
int funny_prototype(int ,int b,float c)
{
}
extern "C"
int extern_c_1(int a, int b)
{
funny_prototype(1,2,3.4);
printf("Moose", );
return 1;
}
extern "C" {
int extern_c_2(int a, int b)
{
return 1;
}
}
// Some operator stuff
class Action
{
// Problems!! operator() and operator[] can not be parsed with semantic
// 1.4.2 but with latest c.by
virtual void operator()(int i, char *p ) = 0;
virtual String& operator[]() = 0;
virtual void operator!() = 0;
virtual void operator->() = 0;
virtual T& operator+=();
virtual T& operator*();
virtual T& operator*=();
};
// class with namespace qualified parents
class Multiinherit : public virtual POA::Parent,
public virtual POA::Parent1,
Parent
{
private:
int i;
public:
Multiinherit();
~Multiinherit();
// method with a list of qualified exceptions
void* throwtest()
throw(Exception0,
Testnamespace::Exception1,
Testnamespace::Excpetion2,
Testnamespace::testnamespace1::Exception3);
};
void*
Multiinherit::throwtest()
throw (Exception0,
Testnamespace::Exception1,
Testnamespace::Excpetion2,
Testnamespace::testnamespace1::Exception3)
{
return;
}
// Jens Rock <jens.rock@asamnet.de>: Nested classes or structs defined
// outside of the containing class/struct.
class container
{
public:
struct contained;
container();
~container();
};
struct container::contained
{
public:
contained();
~contained();
};
/*
* Ok, how about some template stuff.
*/
template <class CT, class container = vector<CT> >
const CT& max (const CT& a, const CT& b)
{
return a < b ? b : a;
}
// Arne Schmitz found this one
std::vector<int> &a, &b, &c;
class TemplateUsingClass
{
typedef TestClassMap::iterator iterator;
typedef map<long, long> TestClassMap;
// typedefs with const and volatile
typedef const map<long, long> const_TestClassMap;
typedef TestClassMap<string>::iterator volatile volatile_iterator;
map<int, int> mapclassvarthingy;
};
template<class T> T ti1(const Foo& foo);
template<> int ti1<int>(const Foo& foo);
// -----------------------------------
// Now some namespace and related stuff
// -----------------------------------
using CORBA::LEX::get_token;
using Namespace1;
using namespace POA::std;
using namespace Test;
namespace Parser
{
namespace
{
using Lexer::get_test;
string str = "";
}
namespace XXX
{
class Foobar : public virtual POA::Parent,
public virtual POA::Parent1,
private POA::list<fact>,
private map<string>
{
int i;
list <shared_ptr<item> >::const_iterator l;
public:
Foobar();
~Foobar();
};
}
void test_function(int i);
};
// unnamed namespaces - even nested
namespace
{
namespace
{
using Lexer::get_test;
string str = "";
class FooClass
{
FooClass();
};
}
// some builtin types
long long ll = 0;
long double d = 0.0;
unsigned test;
unsigned long int **uli = 0;
signed si = 0;
signed short ss = 0;
short int i = 0;
long int li = 0;
// expressions with namespace/class-qualifyiers
ORB_var cGlobalOrb = ORB::_nil();
ORB_var1 cGlobalOrb1 = ORB::_test;
class Testclass
{
#define TEST 0
ini i;
public:
Testclass();
~Testclass();
};
static void test_function(unsigned int i);
};
// outside method implementations which should be grouped to type Test
XXX&
Test::waiting()
{
return;
}
void
Test::print()
{
return;
}
// outside method implementations with namespaces which should be grouped to
// their complete (incl. namespace) types
void*
Parser::XXX::Foobar::wait(int i, const char const * const * p)
{
return;
}
void*
Namespace1::Test::wait1(int i)
{
return;
}
int
Namespace1::Test::waiting(int i)
{
return;
}
// a class with some outside implementations which should all be grouped to
// this class declaration
class ClassWithExternals
{
private:
int i;
public:
ClassWithExternals();
~ClassWithExternals();
void non_nil();
};
// Foobar is not displayed; seems that semantic tries to add this to the class
// Foobar but can not find/display it, because contained in the namespace above.
void
Foobar::non_nil()
{
return;
}
// are correctly grouped to the ClassWithExternals class
void
ClassWithExternals::non_nil()
{
String s = "l<EFBFBD>dfjg dlfgkdlfkgjdl";
return;
}
ClassWithExternals::ClassWithExternals()
{
return;
}
void
ClassWithExternals::~ClassWithExternals()
{
return;
}
// -------------------------------
// Now some macro and define stuff
// -------------------------------
#define TEST 0
#define TEST1 "String"
// The first backslash makes this macro unmatched syntax with semantic 1.4.2!
// With flexing \+newline as nothing all is working fine!
#define MZK_ENTER(METHOD) \
{ \
CzkMethodLog lMethodLog(METHOD,"Framework");\
}
#define ZK_ASSERTM(METHOD,ASSERTION,MESSAGE) \
{ if(!(ASSERTION))\
{\
std::ostringstream lMesgStream; \
lMesgStream << "Assertion failed: " \
<< MESSAGE; \
CzkLogManager::doLog(CzkLogManager::FATAL,"",METHOD, \
"Assert",lMesgStream); \
assert(ASSERTION);\
}\
}
// Test if not newline-backslashes are handled correctly
string s = "My \"quoted\" string";
// parsed fine as macro
#define FOO (arg) method(arg, "foo");
// With semantic 1.4.2 this parsed as macro BAR *and* function method.
// With latest c.bnf at least one-liner macros can be parsed correctly.
#define BAR (arg) CzkMessageLog method(arg, "bar");
// some const and volatile stuff
char * p1 = "Hello"; // 1. variable Pointer, variable Data
const char * p2 = "Hello"; // 2. variable pointer, constant data
char * const p3 = "Hello"; // 3. constant pointer, variable data
const char * const p4 = "Hello"; // 4. constant pointer, constant data
// Case 2 and 4 can exchange first "const" and "char"
char const * p21 = "Hello"; // variable pointer, constant data
char const * const p41 = "Hello"; // constant pointer, constant data
char volatile a = 0; // a volatile char
void foo(bar const &arg); // a reference to a const bar
int foobar(bar const * const p); // a const pointer to a const bar
int foobar(bar const volatile * const p); // a const pointer to a const bar
int foobar3(char* p); // a const pointer to a const bar
// Should not be parsed because this is invalid code
int const & const r3 = i;
boolean i = 0;
boolean & r1 = i;
boolean const & r2 = i;
// const * sequences can be very long in C++ ;-)
char const * const * const * const * ppp;
// complex function declarationen with named pointer-arguments
const char** foobar1(volatile char const * const **p);
const char** foobar11(volatile Test::Namespace::Char<char*> const * const **p);
// complex function declarationen with unnamed pointer-arguments
const char* foobar2(const char***);
const char* foobar21(const Test::Namespace::Char<char>***);
// string literal parsing even with wchar_t
char const *p = "string1";
char const *q = "string1" "str\"ing2" "string3";
wchar_t testc = L'a';
wchar_t const *wp = L"string with a \" in it";
wchar_t const *wq = L"string \n\t\"test" L"string2";
wchar_t const *wr = L"string L";

View File

@@ -1,65 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2007/12/13/rounding-numbers-in-flex-using-the-numberformatter-class/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
verticalAlign="middle"
backgroundColor="white">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.formatters.NumberBaseRoundType;
private function button_click(evt:MouseEvent):void {
textInput.errorString = "";
numberFormatter.format(textInput.text);
if (numberFormatter.error) {
textInput.errorString = numberFormatter.error;
}
arrColl = new ArrayCollection();
numberFormatter.rounding = NumberBaseRoundType.NEAREST;
arrColl.addItem({type:numberFormatter.rounding,
value:numberFormatter.format(textInput.text)});
numberFormatter.rounding = NumberBaseRoundType.UP;
arrColl.addItem({type:numberFormatter.rounding,
value:numberFormatter.format(textInput.text)});
numberFormatter.rounding = NumberBaseRoundType.DOWN;
arrColl.addItem({type:numberFormatter.rounding,
value:numberFormatter.format(textInput.text)});
numberFormatter.rounding = NumberBaseRoundType.NONE;
arrColl.addItem({type:numberFormatter.rounding,
value:numberFormatter.format(textInput.text)});
}
]]>
</mx:Script>
<mx:ArrayCollection id="arrColl" />
<mx:NumberFormatter id="numberFormatter"
precision="2"
rounding="up" />
<mx:ApplicationControlBar dock="true">
<mx:Form styleName="plain">
<mx:FormItem label="number:"
direction="horizontal">
<mx:TextInput id="textInput"
text="2.0499"
restrict="[0-9.-]"
maxChars="6" />
<mx:Button label="format"
click="button_click(event);" />
</mx:FormItem>
</mx:Form>
</mx:ApplicationControlBar>
<mx:DataGrid id="dataGrid"
dataProvider="{arrColl}"
rowCount="4" />
</mx:Application>

View File

@@ -1,98 +0,0 @@
(* $Id: fifteen.ml,v 1.8 2001/09/06 08:47:55 garrigue Exp $ *)
open StdLabels
open Gaux
open Gtk
open GObj
open GMain
class position ~init_x ~init_y ~min_x ~min_y ~max_x ~max_y = object
val mutable x = init_x
val mutable y = init_y
method current = (x, y)
method up () = if y > min_y then y <- y-1 else (); (x, y)
method down () = if y < max_y then y <- y+1 else (); (x, y)
method left () = if x > min_x then x <- x-1 else (); (x, y)
method right () = if x < max_x then x <- x+1 else (); (x, y)
end
let game_init () = (* generate initial puzzle state *)
let rec game_aux acc rest n_invert =
let len = List.length rest in
if len=0 then
if n_invert mod 2 = 0 then
acc (* to be solvable, n_invert must be even *)
else
(List.hd (List.tl acc))::(List.hd acc)::(List.tl (List.tl acc))
else begin
let rec extract n xs =
if (n=0) then (List.hd xs, List.tl xs)
else
let (ans, ys) = extract (n-1) (List.tl xs) in
(ans, List.hd xs :: ys) in
let ran = Random.int len in
let (elm, rest1) = extract ran rest in
let rec count p xs = match xs with
[] -> 0
| y :: ys -> let acc = count p ys in
if p y then 1+acc else acc
in
let new_n_invert = count (fun x -> elm > x) acc in
game_aux (elm :: acc) rest1 (n_invert+new_n_invert)
end in
let rec from n = if n=0 then [] else n :: from (n-1) in
game_aux [] (from 15) 0
let _ = Random.init (int_of_float (Sys.time () *. 1000.))
let window = GWindow.window ()
let _ = window#connect#destroy ~callback:GMain.Main.quit
let tbl = GPack.table ~rows:4 ~columns:4 ~homogeneous:true ~packing:window#add ()
let dummy = GMisc.label ~text:"" ~packing:(tbl#attach ~left:3 ~top:3) ()
let arr = Array.create_matrix ~dimx:4 ~dimy:4 dummy
let init = game_init ()
let _ =
for i = 0 to 15 do
let j = i mod 4 in
let k = i/4 in
let frame =
GBin.frame ~shadow_type:`OUT ~width:32 ~height:32
~packing:(tbl#attach ~left:j ~top:k) () in
if i < 15 then
arr.(j).(k) <-
GMisc.label ~text:(string_of_int (List.nth init i))
~packing:frame#add ()
done
let pos = new position ~init_x:3 ~init_y:3 ~min_x:0 ~min_y:0 ~max_x:3 ~max_y:3
open GdkKeysyms
let _ =
window#event#connect#key_press ~callback:
begin fun ev ->
let (x0, y0) = pos#current in
let wid0 = arr.(x0).(y0) in
let key = GdkEvent.Key.keyval ev in
if key = _q || key = _Escape then (Main.quit (); exit 0) else
let (x1, y1) =
if key = _h || key = _Left then
pos#right ()
else if key = _j || key = _Down then
pos#up ()
else if key = _k || key = _Up then
pos#down ()
else if key = _l || key = _Right then
pos#left ()
else (x0, y0)
in
let wid1 = arr.(x1).(y1) in
wid0#set_text (wid1#text);
wid1#set_text "";
true
end
let main () =
window#show ();
Main.main ()
let _ = main ()

View File

@@ -1,153 +0,0 @@
(************************************************************************)
(* v * The Coq Proof Assistant / The Coq Development Team *)
(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
(* \VV/ **************************************************************)
(* // * This file is distributed under the terms of the *)
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
(* $Id$ *)
(*s Heaps *)
module type Ordered = sig
type t
val compare : t -> t -> int
end
module type S =sig
(* Type of functional heaps *)
type t
(* Type of elements *)
type elt
(* The empty heap *)
val empty : t
(* [add x h] returns a new heap containing the elements of [h], plus [x];
complexity $O(log(n))$ *)
val add : elt -> t -> t
(* [maximum h] returns the maximum element of [h]; raises [EmptyHeap]
when [h] is empty; complexity $O(1)$ *)
val maximum : t -> elt
(* [remove h] returns a new heap containing the elements of [h], except
the maximum of [h]; raises [EmptyHeap] when [h] is empty;
complexity $O(log(n))$ *)
val remove : t -> t
(* usual iterators and combinators; elements are presented in
arbitrary order *)
val iter : (elt -> unit) -> t -> unit
val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a
end
exception EmptyHeap
(*s Functional implementation *)
module Functional(X : Ordered) = struct
(* Heaps are encoded as complete binary trees, i.e., binary trees
which are full expect, may be, on the bottom level where it is filled
from the left.
These trees also enjoy the heap property, namely the value of any node
is greater or equal than those of its left and right subtrees.
There are 4 kinds of complete binary trees, denoted by 4 constructors:
[FFF] for a full binary tree (and thus 2 full subtrees);
[PPF] for a partial tree with a partial left subtree and a full
right subtree;
[PFF] for a partial tree with a full left subtree and a full right subtree
(but of different heights);
and [PFP] for a partial tree with a full left subtree and a partial
right subtree. *)
type t =
| Empty
| FFF of t * X.t * t (* full (full, full) *)
| PPF of t * X.t * t (* partial (partial, full) *)
| PFF of t * X.t * t (* partial (full, full) *)
| PFP of t * X.t * t (* partial (full, partial) *)
type elt = X.t
let empty = Empty
(* smart constructors for insertion *)
let p_f l x r = match l with
| Empty | FFF _ -> PFF (l, x, r)
| _ -> PPF (l, x, r)
let pf_ l x = function
| Empty | FFF _ as r -> FFF (l, x, r)
| r -> PFP (l, x, r)
let rec add x = function
| Empty ->
FFF (Empty, x, Empty)
(* insertion to the left *)
| FFF (l, y, r) | PPF (l, y, r) ->
if X.compare x y > 0 then p_f (add y l) x r else p_f (add x l) y r
(* insertion to the right *)
| PFF (l, y, r) | PFP (l, y, r) ->
if X.compare x y > 0 then pf_ l x (add y r) else pf_ l y (add x r)
let maximum = function
| Empty -> raise EmptyHeap
| FFF (_, x, _) | PPF (_, x, _) | PFF (_, x, _) | PFP (_, x, _) -> x
(* smart constructors for removal; note that they are different
from the ones for insertion! *)
let p_f l x r = match l with
| Empty | FFF _ -> FFF (l, x, r)
| _ -> PPF (l, x, r)
let pf_ l x = function
| Empty | FFF _ as r -> PFF (l, x, r)
| r -> PFP (l, x, r)
let rec remove = function
| Empty ->
raise EmptyHeap
| FFF (Empty, _, Empty) ->
Empty
| PFF (l, _, Empty) ->
l
(* remove on the left *)
| PPF (l, x, r) | PFF (l, x, r) ->
let xl = maximum l in
let xr = maximum r in
let l' = remove l in
if X.compare xl xr >= 0 then
p_f l' xl r
else
p_f l' xr (add xl (remove r))
(* remove on the right *)
| FFF (l, x, r) | PFP (l, x, r) ->
let xl = maximum l in
let xr = maximum r in
let r' = remove r in
if X.compare xl xr > 0 then
pf_ (add xr (remove l)) xl r'
else
pf_ l xr r'
let rec iter f = function
| Empty ->
()
| FFF (l, x, r) | PPF (l, x, r) | PFF (l, x, r) | PFP (l, x, r) ->
iter f l; f x; iter f r
let rec fold f h x0 = match h with
| Empty ->
x0
| FFF (l, x, r) | PPF (l, x, r) | PFF (l, x, r) | PFP (l, x, r) ->
fold f l (fold f r (f x x0))
end

View File

@@ -1,294 +0,0 @@
(* ========================================================================= *)
(* Knuth-Bendix completion done by HOL inference. John Harrison 2005 *)
(* *)
(* This was written by fairly mechanical modification of the code at *)
(* *)
(* http://www.cl.cam.ac.uk/users/jrh/atp/order.ml *)
(* http://www.cl.cam.ac.uk/users/jrh/atp/completion.ml *)
(* *)
(* for HOL's slightly different term structure, with ad hoc term *)
(* manipulations replaced by inference on equational theorems. We also have *)
(* the optimization of throwing left-reducible rules back into the set of *)
(* critical pairs. However, we don't prioritize smaller critical pairs or *)
(* anything like that; this is still a very naive implementation. *)
(* *)
(* For something very similar done 15 years ago, see Konrad Slind's Master's *)
(* thesis: "An Implementation of Higher Order Logic", U Calgary 1991. *)
(* ========================================================================= *)
let is_realvar w x = is_var x & not(mem x w);;
let rec real_strip w tm =
if mem tm w then tm,[] else
let l,r = dest_comb tm in
let f,args = real_strip w l in f,args@[r];;
(* ------------------------------------------------------------------------- *)
(* Construct a weighting function. *)
(* ------------------------------------------------------------------------- *)
let weight lis (f,n) (g,m) =
let i = index f lis and j = index g lis in
i > j or i = j & n > m;;
(* ------------------------------------------------------------------------- *)
(* Generic lexicographic ordering function. *)
(* ------------------------------------------------------------------------- *)
let rec lexord ord l1 l2 =
match (l1,l2) with
(h1::t1,h2::t2) -> if ord h1 h2 then length t1 = length t2
else h1 = h2 & lexord ord t1 t2
| _ -> false;;
(* ------------------------------------------------------------------------- *)
(* Lexicographic path ordering. Note that we also use the weights *)
(* to define the set of constants, so they don't literally have to be *)
(* constants in the HOL sense. *)
(* ------------------------------------------------------------------------- *)
let rec lpo_gt w s t =
if is_realvar w t then not(s = t) & mem t (frees s)
else if is_realvar w s or is_abs s or is_abs t then false else
let f,fargs = real_strip w s and g,gargs = real_strip w t in
exists (fun si -> lpo_ge w si t) fargs or
forall (lpo_gt w s) gargs &
(f = g & lexord (lpo_gt w) fargs gargs or
weight w (f,length fargs) (g,length gargs))
and lpo_ge w s t = (s = t) or lpo_gt w s t;;
(* ------------------------------------------------------------------------- *)
(* Unification. Again we have the weights "w" fixing the set of constants. *)
(* ------------------------------------------------------------------------- *)
let rec istriv w env x t =
if is_realvar w t then t = x or defined env t & istriv w env x (apply env t)
else if is_const t then false else
let f,args = strip_comb t in
exists (istriv w env x) args & failwith "cyclic";;
let rec unify w env tp =
match tp with
((Var(_,_) as x),t) | (t,(Var(_,_) as x)) when not(mem x w) ->
if defined env x then unify w env (apply env x,t)
else if istriv w env x t then env else (x|->t) env
| (Comb(f,x),Comb(g,y)) -> unify w (unify w env (x,y)) (f,g)
| (s,t) -> if s = t then env else failwith "unify: not unifiable";;
(* ------------------------------------------------------------------------- *)
(* Full unification, unravelling graph into HOL-style instantiation list. *)
(* ------------------------------------------------------------------------- *)
let fullunify w (s,t) =
let env = unify w undefined (s,t) in
let th = map (fun (x,t) -> (t,x)) (graph env) in
let rec subs t =
let t' = vsubst th t in
if t' = t then t else subs t' in
map (fun (t,x) -> (subs t,x)) th;;
(* ------------------------------------------------------------------------- *)
(* Construct "overlaps": ways of rewriting subterms using unification. *)
(* ------------------------------------------------------------------------- *)
let LIST_MK_COMB f ths = rev_itlist (fun s t -> MK_COMB(t,s)) ths (REFL f);;
let rec listcases fn rfn lis acc =
match lis with
[] -> acc
| h::t -> fn h (fun i h' -> rfn i (h'::map REFL t)) @
listcases fn (fun i t' -> rfn i (REFL h::t')) t acc;;
let rec overlaps w th tm rfn =
let l,r = dest_eq(concl th) in
if not (is_comb tm) then [] else
let f,args = strip_comb tm in
listcases (overlaps w th) (fun i a -> rfn i (LIST_MK_COMB f a)) args
(try [rfn (fullunify w (l,tm)) th] with Failure _ -> []);;
(* ------------------------------------------------------------------------- *)
(* Rename variables canonically to avoid clashes or remove redundancy. *)
(* ------------------------------------------------------------------------- *)
let fixvariables s th =
let fvs = subtract (frees(concl th)) (freesl(hyp th)) in
let gvs = map2 (fun v n -> mk_var(s^string_of_int n,type_of v))
fvs (1--(length fvs)) in
INST (zip gvs fvs) th;;
let renamepair (th1,th2) = fixvariables "x" th1,fixvariables "y" th2;;
(* ------------------------------------------------------------------------- *)
(* Find all critical pairs. *)
(* ------------------------------------------------------------------------- *)
let crit1 w eq1 eq2 =
let l1,r1 = dest_eq(concl eq1)
and l2,r2 = dest_eq(concl eq2) in
overlaps w eq1 l2 (fun i th -> TRANS (SYM(INST i th)) (INST i eq2));;
let thm_union l1 l2 =
itlist (fun th ths -> let th' = fixvariables "x" th in
let tm = concl th' in
if exists (fun th'' -> concl th'' = tm) ths then ths
else th'::ths)
l1 l2;;
let critical_pairs w tha thb =
let th1,th2 = renamepair (tha,thb) in
if concl th1 = concl th2 then crit1 w th1 th2 else
filter (fun th -> let l,r = dest_eq(concl th) in l <> r)
(thm_union (crit1 w th1 th2) (thm_union (crit1 w th2 th1) []));;
(* ------------------------------------------------------------------------- *)
(* Normalize an equation and try to orient it. *)
(* ------------------------------------------------------------------------- *)
let normalize_and_orient w eqs th =
let th' = GEN_REWRITE_RULE TOP_DEPTH_CONV eqs th in
let s',t' = dest_eq(concl th') in
if lpo_ge w s' t' then th' else if lpo_ge w t' s' then SYM th'
else failwith "Can't orient equation";;
(* ------------------------------------------------------------------------- *)
(* Print out status report to reduce user boredom. *)
(* ------------------------------------------------------------------------- *)
let status(eqs,crs) eqs0 =
if eqs = eqs0 & (length crs) mod 1000 <> 0 then () else
(print_string(string_of_int(length eqs)^" equations and "^
string_of_int(length crs)^" pending critical pairs");
print_newline());;
(* ------------------------------------------------------------------------- *)
(* Basic completion, throwing back left-reducible rules. *)
(* ------------------------------------------------------------------------- *)
let left_reducible eqs eq =
can (CHANGED_CONV(GEN_REWRITE_CONV (LAND_CONV o ONCE_DEPTH_CONV) eqs))
(concl eq);;
let rec complete w (eqs,crits) =
match crits with
(eq::ocrits) ->
let trip =
try let eq' = normalize_and_orient w eqs eq in
let s',t' = dest_eq(concl eq') in
if s' = t' then (eqs,ocrits) else
let crits',eqs' = partition(left_reducible [eq']) eqs in
let eqs'' = eq'::eqs' in
eqs'',
ocrits @ crits' @ itlist ((@) o critical_pairs w eq') eqs'' []
with Failure _ ->
if exists (can (normalize_and_orient w eqs)) ocrits
then (eqs,ocrits@[eq])
else failwith "complete: no orientable equations" in
status trip eqs; complete w trip
| [] -> eqs;;
(* ------------------------------------------------------------------------- *)
(* Overall completion. *)
(* ------------------------------------------------------------------------- *)
let complete_equations wts eqs =
let eqs' = map (normalize_and_orient wts []) eqs in
complete wts ([],eqs');;
(* ------------------------------------------------------------------------- *)
(* Knuth-Bendix example 4: the inverse property. *)
(* ------------------------------------------------------------------------- *)
complete_equations [`1`; `(*):num->num->num`; `i:num->num`]
[SPEC_ALL(ASSUME `!a b. i(a) * a * b = b`)];;
(* ------------------------------------------------------------------------- *)
(* Knuth-Bendix example 6: central groupoids. *)
(* ------------------------------------------------------------------------- *)
complete_equations [`(*):num->num->num`]
[SPEC_ALL(ASSUME `!a b c. (a * b) * (b * c) = b`)];;
(* ------------------------------------------------------------------------- *)
(* Knuth-Bendix example 9: cancellation law. *)
(* ------------------------------------------------------------------------- *)
complete_equations
[`1`; `( * ):num->num->num`; `(+):num->num->num`; `(-):num->num->num`]
(map SPEC_ALL (CONJUNCTS (ASSUME
`(!a b:num. a - a * b = b) /\
(!a b:num. a * b - b = a) /\
(!a. a * 1 = a) /\
(!a. 1 * a = a)`)));;
(* ------------------------------------------------------------------------- *)
(* Another example: pure congruence closure (no variables). *)
(* ------------------------------------------------------------------------- *)
complete_equations [`c:A`; `f:A->A`]
(map SPEC_ALL (CONJUNCTS (ASSUME
`((f(f(f(f(f c))))) = c:A) /\ (f(f(f c)) = c)`)));;
(* ------------------------------------------------------------------------- *)
(* Knuth-Bendix example 1: group theory. *)
(* ------------------------------------------------------------------------- *)
let eqs = map SPEC_ALL (CONJUNCTS (ASSUME
`(!x. 1 * x = x) /\ (!x. i(x) * x = 1) /\
(!x y z. (x * y) * z = x * y * z)`));;
complete_equations [`1`; `(*):num->num->num`; `i:num->num`] eqs;;
(* ------------------------------------------------------------------------- *)
(* Near-rings (from Aichinger's Diplomarbeit). *)
(* ------------------------------------------------------------------------- *)
let eqs = map SPEC_ALL (CONJUNCTS (ASSUME
`(!x. 0 + x = x) /\
(!x. neg x + x = 0) /\
(!x y z. (x + y) + z = x + y + z) /\
(!x y z. (x * y) * z = x * y * z) /\
(!x y z. (x + y) * z = (x * z) + (y * z))`));;
let nreqs =
complete_equations
[`0`; `(+):num->num->num`; `neg:num->num`; `( * ):num->num->num`] eqs;;
(*** This weighting also works OK, though the system is a bit bigger
let nreqs =
complete_equations
[`0`; `(+):num->num->num`; `( * ):num->num->num`; `INV`] eqs;;
****)
(* ------------------------------------------------------------------------- *)
(* A "completion" tactic. *)
(* ------------------------------------------------------------------------- *)
let COMPLETE_TAC w th =
let eqs = map SPEC_ALL (CONJUNCTS(SPEC_ALL th)) in
let eqs' = complete_equations w eqs in
MAP_EVERY (ASSUME_TAC o GEN_ALL) eqs';;
(* ------------------------------------------------------------------------- *)
(* Solve example problems in gr *)
g `(!x. 1 * x = x) /\
(!x. i(x) * x = 1) /\
(!x y z. (x * y) * z = x * y * z)
==> !x y. i(y) * i(i(i(x * i(y)))) * x = 1`;;
e (DISCH_THEN(COMPLETE_TAC [`1`; `(*):num->num->num`; `i:num->num`]));;
e (ASM_REWRITE_TAC[]);;
g `(!x. 0 + x = x) /\
(!x. neg x + x = 0) /\
(!x y z. (x + y) + z = x + y + z) /\
(!x y z. (x * y) * z = x * y * z) /\
(!x y z. (x + y) * z = (x * z) + (y * z))
==> (neg 0 * (x * y + z + neg(neg(w + z))) + neg(neg b + neg a) =
a + b)`;;
e (DISCH_THEN(COMPLETE_TAC
[`0`; `(+):num->num->num`; `neg:num->num`; `( * ):num->num->num`]));;
e (ASM_REWRITE_TAC[]);;

View File

@@ -1,82 +0,0 @@
(*
* Xml Light, an small Xml parser/printer with DTD support.
* Copyright (C) 2003 Nicolas Cannasse (ncannasse@motion-twin.com)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library has the special exception on linking described in file
* README.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*)
(** Xml Light Parser
While basic parsing functions can be used in the {!Xml} module, this module
is providing a way to create, configure and run an Xml parser.
*)
(** Abstract type for an Xml parser. *)
type t
(** Several kind of resources can contain Xml documents. *)
type source =
| SFile of string
| SChannel of in_channel
| SString of string
| SLexbuf of Lexing.lexbuf
(** This function returns a new parser with default options. *)
val make : unit -> t
(** This function enable or disable automatic DTD proving with the parser.
Note that Xml documents having no reference to a DTD are never proved
when parsed (but you can prove them later using the {!Dtd} module
{i (by default, prove is true)}. *)
val prove : t -> bool -> unit
(** When parsing an Xml document from a file using the {!Xml.parse_file}
function, the DTD file if declared by the Xml document has to be in the
same directory as the xml file. When using other parsing functions,
such as on a string or on a channel, the parser will raise everytime
{!Xml.File_not_found} if a DTD file is needed and prove enabled. To enable
the DTD loading of the file, the user have to configure the Xml parser
with a [resolve] function which is taking as argument the DTD filename and
is returning a checked DTD. The user can then implement any kind of DTD
loading strategy, and can use the {!Dtd} module functions to parse and check
the DTD file {i (by default, the resolve function is raising}
{!Xml.File_not_found}). *)
val resolve : t -> (string -> Dtd.checked) -> unit
(** When a Xml document is parsed, the parser will check that the end of the
document is reached, so for example parsing ["<A/><B/>"] will fail instead
of returning only the A element. You can turn off this check by setting
[check_eof] to [false] {i (by default, check_eof is true)}. *)
val check_eof : t -> bool -> unit
(** Once the parser is configurated, you can run the parser on a any kind
of xml document source to parse its contents into an Xml data structure. *)
val parse : t -> source -> Xml.xml
(** When several PCData elements are separed by a \n (or \r\n), you can
either split the PCData in two distincts PCData or merge them with \n
as seperator into one PCData. The default behavior is to concat the
PCData, but this can be changed for a given parser with this flag. *)
val concat_pcdata : t -> bool -> unit
(**/**)
(* internal usage only... *)
val _raises : (Xml.error_msg -> Lexing.lexbuf -> exn) -> (string -> exn) -> (Dtd.parse_error_msg -> Lexing.lexbuf -> exn) -> unit

View File

@@ -1,721 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\DomCrawler;
use Symfony\Component\CssSelector\CssSelector;
/**
* Crawler eases navigation of a list of \DOMNode objects.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @api
*/
class Crawler extends \SplObjectStorage
{
/**
* @var string The current URI or the base href value
*/
private $uri;
/**
* Constructor.
*
* @param mixed $node A Node to use as the base for the crawling
* @param string $uri The current URI or the base href value
*
* @api
*/
public function __construct($node = null, $uri = null)
{
$this->uri = $uri;
$this->add($node);
}
/**
* Removes all the nodes.
*
* @api
*/
public function clear()
{
$this->removeAll($this);
}
/**
* Adds a node to the current list of nodes.
*
* This method uses the appropriate specialized add*() method based
* on the type of the argument.
*
* @param null|\DOMNodeList|array|\DOMNode $node A node
*
* @api
*/
public function add($node)
{
if ($node instanceof \DOMNodeList) {
$this->addNodeList($node);
} elseif (is_array($node)) {
$this->addNodes($node);
} elseif (is_string($node)) {
$this->addContent($node);
} elseif (is_object($node)) {
$this->addNode($node);
}
}
/**
* Adds HTML/XML content.
*
* @param string $content A string to parse as HTML/XML
* @param null|string $type The content type of the string
*
* @return null|void
*/
public function addContent($content, $type = null)
{
if (empty($type)) {
$type = 'text/html';
}
// DOM only for HTML/XML content
if (!preg_match('/(x|ht)ml/i', $type, $matches)) {
return null;
}
$charset = 'ISO-8859-1';
if (false !== $pos = strpos($type, 'charset=')) {
$charset = substr($type, $pos + 8);
if (false !== $pos = strpos($charset, ';')) {
$charset = substr($charset, 0, $pos);
}
}
if ('x' === $matches[1]) {
$this->addXmlContent($content, $charset);
} else {
$this->addHtmlContent($content, $charset);
}
}
/**
* Adds an HTML content to the list of nodes.
*
* The libxml errors are disabled when the content is parsed.
*
* If you want to get parsing errors, be sure to enable
* internal errors via libxml_use_internal_errors(true)
* and then, get the errors via libxml_get_errors(). Be
* sure to clear errors with libxml_clear_errors() afterward.
*
* @param string $content The HTML content
* @param string $charset The charset
*
* @api
*/
public function addHtmlContent($content, $charset = 'UTF-8')
{
$dom = new \DOMDocument('1.0', $charset);
$dom->validateOnParse = true;
if (function_exists('mb_convert_encoding')) {
$content = mb_convert_encoding($content, 'HTML-ENTITIES', $charset);
}
$current = libxml_use_internal_errors(true);
@$dom->loadHTML($content);
libxml_use_internal_errors($current);
$this->addDocument($dom);
$base = $this->filterXPath('descendant-or-self::base')->extract(array('href'));
if (count($base)) {
$this->uri = current($base);
}
}
/**
* Adds an XML content to the list of nodes.
*
* The libxml errors are disabled when the content is parsed.
*
* If you want to get parsing errors, be sure to enable
* internal errors via libxml_use_internal_errors(true)
* and then, get the errors via libxml_get_errors(). Be
* sure to clear errors with libxml_clear_errors() afterward.
*
* @param string $content The XML content
* @param string $charset The charset
*
* @api
*/
public function addXmlContent($content, $charset = 'UTF-8')
{
$dom = new \DOMDocument('1.0', $charset);
$dom->validateOnParse = true;
// remove the default namespace to make XPath expressions simpler
$current = libxml_use_internal_errors(true);
@$dom->loadXML(str_replace('xmlns', 'ns', $content));
libxml_use_internal_errors($current);
$this->addDocument($dom);
}
/**
* Adds a \DOMDocument to the list of nodes.
*
* @param \DOMDocument $dom A \DOMDocument instance
*
* @api
*/
public function addDocument(\DOMDocument $dom)
{
if ($dom->documentElement) {
$this->addNode($dom->documentElement);
}
}
/**
* Adds a \DOMNodeList to the list of nodes.
*
* @param \DOMNodeList $nodes A \DOMNodeList instance
*
* @api
*/
public function addNodeList(\DOMNodeList $nodes)
{
foreach ($nodes as $node) {
$this->addNode($node);
}
}
/**
* Adds an array of \DOMNode instances to the list of nodes.
*
* @param array $nodes An array of \DOMNode instances
*
* @api
*/
public function addNodes(array $nodes)
{
foreach ($nodes as $node) {
$this->add($node);
}
}
/**
* Adds a \DOMNode instance to the list of nodes.
*
* @param \DOMNode $node A \DOMNode instance
*
* @api
*/
public function addNode(\DOMNode $node)
{
if ($node instanceof \DOMDocument) {
$this->attach($node->documentElement);
} else {
$this->attach($node);
}
}
/**
* Returns a node given its position in the node list.
*
* @param integer $position The position
*
* @return Crawler A new instance of the Crawler with the selected node, or an empty Crawler if it does not exist.
*
* @api
*/
public function eq($position)
{
foreach ($this as $i => $node) {
if ($i == $position) {
return new static($node, $this->uri);
}
}
return new static(null, $this->uri);
}
/**
* Calls an anonymous function on each node of the list.
*
* The anonymous function receives the position and the node as arguments.
*
* Example:
*
* $crawler->filter('h1')->each(function ($node, $i)
* {
* return $node->nodeValue;
* });
*
* @param \Closure $closure An anonymous function
*
* @return array An array of values returned by the anonymous function
*
* @api
*/
public function each(\Closure $closure)
{
$data = array();
foreach ($this as $i => $node) {
$data[] = $closure($node, $i);
}
return $data;
}
/**
* Reduces the list of nodes by calling an anonymous function.
*
* To remove a node from the list, the anonymous function must return false.
*
* @param \Closure $closure An anonymous function
*
* @return Crawler A Crawler instance with the selected nodes.
*
* @api
*/
public function reduce(\Closure $closure)
{
$nodes = array();
foreach ($this as $i => $node) {
if (false !== $closure($node, $i)) {
$nodes[] = $node;
}
}
return new static($nodes, $this->uri);
}
/**
* Returns the first node of the current selection
*
* @return Crawler A Crawler instance with the first selected node
*
* @api
*/
public function first()
{
return $this->eq(0);
}
/**
* Returns the last node of the current selection
*
* @return Crawler A Crawler instance with the last selected node
*
* @api
*/
public function last()
{
return $this->eq(count($this) - 1);
}
/**
* Returns the siblings nodes of the current selection
*
* @return Crawler A Crawler instance with the sibling nodes
*
* @throws \InvalidArgumentException When current node is empty
*
* @api
*/
public function siblings()
{
if (!count($this)) {
throw new \InvalidArgumentException('The current node list is empty.');
}
return new static($this->sibling($this->getNode(0)->parentNode->firstChild), $this->uri);
}
/**
* Returns the next siblings nodes of the current selection
*
* @return Crawler A Crawler instance with the next sibling nodes
*
* @throws \InvalidArgumentException When current node is empty
*
* @api
*/
public function nextAll()
{
if (!count($this)) {
throw new \InvalidArgumentException('The current node list is empty.');
}
return new static($this->sibling($this->getNode(0)), $this->uri);
}
/**
* Returns the previous sibling nodes of the current selection
*
* @return Crawler A Crawler instance with the previous sibling nodes
*
* @api
*/
public function previousAll()
{
if (!count($this)) {
throw new \InvalidArgumentException('The current node list is empty.');
}
return new static($this->sibling($this->getNode(0), 'previousSibling'), $this->uri);
}
/**
* Returns the parents nodes of the current selection
*
* @return Crawler A Crawler instance with the parents nodes of the current selection
*
* @throws \InvalidArgumentException When current node is empty
*
* @api
*/
public function parents()
{
if (!count($this)) {
throw new \InvalidArgumentException('The current node list is empty.');
}
$node = $this->getNode(0);
$nodes = array();
while ($node = $node->parentNode) {
if (1 === $node->nodeType && '_root' !== $node->nodeName) {
$nodes[] = $node;
}
}
return new static($nodes, $this->uri);
}
/**
* Returns the children nodes of the current selection
*
* @return Crawler A Crawler instance with the children nodes
*
* @throws \InvalidArgumentException When current node is empty
*
* @api
*/
public function children()
{
if (!count($this)) {
throw new \InvalidArgumentException('The current node list is empty.');
}
return new static($this->sibling($this->getNode(0)->firstChild), $this->uri);
}
/**
* Returns the attribute value of the first node of the list.
*
* @param string $attribute The attribute name
*
* @return string The attribute value
*
* @throws \InvalidArgumentException When current node is empty
*
* @api
*/
public function attr($attribute)
{
if (!count($this)) {
throw new \InvalidArgumentException('The current node list is empty.');
}
return $this->getNode(0)->getAttribute($attribute);
}
/**
* Returns the node value of the first node of the list.
*
* @return string The node value
*
* @throws \InvalidArgumentException When current node is empty
*
* @api
*/
public function text()
{
if (!count($this)) {
throw new \InvalidArgumentException('The current node list is empty.');
}
return $this->getNode(0)->nodeValue;
}
/**
* Extracts information from the list of nodes.
*
* You can extract attributes or/and the node value (_text).
*
* Example:
*
* $crawler->filter('h1 a')->extract(array('_text', 'href'));
*
* @param array $attributes An array of attributes
*
* @return array An array of extracted values
*
* @api
*/
public function extract($attributes)
{
$attributes = (array) $attributes;
$data = array();
foreach ($this as $node) {
$elements = array();
foreach ($attributes as $attribute) {
if ('_text' === $attribute) {
$elements[] = $node->nodeValue;
} else {
$elements[] = $node->getAttribute($attribute);
}
}
$data[] = count($attributes) > 1 ? $elements : $elements[0];
}
return $data;
}
/**
* Filters the list of nodes with an XPath expression.
*
* @param string $xpath An XPath expression
*
* @return Crawler A new instance of Crawler with the filtered list of nodes
*
* @api
*/
public function filterXPath($xpath)
{
$document = new \DOMDocument('1.0', 'UTF-8');
$root = $document->appendChild($document->createElement('_root'));
foreach ($this as $node) {
$root->appendChild($document->importNode($node, true));
}
$domxpath = new \DOMXPath($document);
return new static($domxpath->query($xpath), $this->uri);
}
/**
* Filters the list of nodes with a CSS selector.
*
* This method only works if you have installed the CssSelector Symfony Component.
*
* @param string $selector A CSS selector
*
* @return Crawler A new instance of Crawler with the filtered list of nodes
*
* @throws \RuntimeException if the CssSelector Component is not available
*
* @api
*/
public function filter($selector)
{
if (!class_exists('Symfony\\Component\\CssSelector\\CssSelector')) {
// @codeCoverageIgnoreStart
throw new \RuntimeException('Unable to filter with a CSS selector as the Symfony CssSelector is not installed (you can use filterXPath instead).');
// @codeCoverageIgnoreEnd
}
return $this->filterXPath(CssSelector::toXPath($selector));
}
/**
* Selects links by name or alt value for clickable images.
*
* @param string $value The link text
*
* @return Crawler A new instance of Crawler with the filtered list of nodes
*
* @api
*/
public function selectLink($value)
{
$xpath = sprintf('//a[contains(concat(\' \', normalize-space(string(.)), \' \'), %s)] ', static::xpathLiteral(' '.$value.' ')).
sprintf('| //a/img[contains(concat(\' \', normalize-space(string(@alt)), \' \'), %s)]/ancestor::a', static::xpathLiteral(' '.$value.' '));
return $this->filterXPath($xpath);
}
/**
* Selects a button by name or alt value for images.
*
* @param string $value The button text
*
* @return Crawler A new instance of Crawler with the filtered list of nodes
*
* @api
*/
public function selectButton($value)
{
$xpath = sprintf('//input[((@type="submit" or @type="button") and contains(concat(\' \', normalize-space(string(@value)), \' \'), %s)) ', static::xpathLiteral(' '.$value.' ')).
sprintf('or (@type="image" and contains(concat(\' \', normalize-space(string(@alt)), \' \'), %s)) or @id="%s" or @name="%s"] ', static::xpathLiteral(' '.$value.' '), $value, $value).
sprintf('| //button[contains(concat(\' \', normalize-space(string(.)), \' \'), %s) or @id="%s" or @name="%s"]', static::xpathLiteral(' '.$value.' '), $value, $value);
return $this->filterXPath($xpath);
}
/**
* Returns a Link object for the first node in the list.
*
* @param string $method The method for the link (get by default)
*
* @return Link A Link instance
*
* @throws \InvalidArgumentException If the current node list is empty
*
* @api
*/
public function link($method = 'get')
{
if (!count($this)) {
throw new \InvalidArgumentException('The current node list is empty.');
}
$node = $this->getNode(0);
return new Link($node, $this->uri, $method);
}
/**
* Returns an array of Link objects for the nodes in the list.
*
* @return array An array of Link instances
*
* @api
*/
public function links()
{
$links = array();
foreach ($this as $node) {
$links[] = new Link($node, $this->uri, 'get');
}
return $links;
}
/**
* Returns a Form object for the first node in the list.
*
* @param array $values An array of values for the form fields
* @param string $method The method for the form
*
* @return Form A Form instance
*
* @throws \InvalidArgumentException If the current node list is empty
*
* @api
*/
public function form(array $values = null, $method = null)
{
if (!count($this)) {
throw new \InvalidArgumentException('The current node list is empty.');
}
$form = new Form($this->getNode(0), $this->uri, $method);
if (null !== $values) {
$form->setValues($values);
}
return $form;
}
/**
* Converts string for XPath expressions.
*
* Escaped characters are: quotes (") and apostrophe (').
*
* Examples:
* <code>
* echo Crawler::xpathLiteral('foo " bar');
* //prints 'foo " bar'
*
* echo Crawler::xpathLiteral("foo ' bar");
* //prints "foo ' bar"
*
* echo Crawler::xpathLiteral('a\'b"c');
* //prints concat('a', "'", 'b"c')
* </code>
*
* @param string $s String to be escaped
*
* @return string Converted string
*
*/
public static function xpathLiteral($s)
{
if (false === strpos($s, "'")) {
return sprintf("'%s'", $s);
}
if (false === strpos($s, '"')) {
return sprintf('"%s"', $s);
}
$string = $s;
$parts = array();
while (true) {
if (false !== $pos = strpos($string, "'")) {
$parts[] = sprintf("'%s'", substr($string, 0, $pos));
$parts[] = "\"'\"";
$string = substr($string, $pos + 1);
} else {
$parts[] = "'$string'";
break;
}
}
return sprintf("concat(%s)", implode($parts, ', '));
}
private function getNode($position)
{
foreach ($this as $i => $node) {
if ($i == $position) {
return $node;
}
// @codeCoverageIgnoreStart
}
return null;
// @codeCoverageIgnoreEnd
}
private function sibling($node, $siblingDir = 'nextSibling')
{
$nodes = array();
do {
if ($node !== $this->getNode(0) && $node->nodeType === 1) {
$nodes[] = $node;
}
} while ($node = $node->$siblingDir);
return $nodes;
}
}

View File

@@ -1,157 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\DomCrawler;
/**
* Link represents an HTML link (an HTML a tag).
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @api
*/
class Link
{
/**
* @var \DOMNode A \DOMNode instance
*/
protected $node;
/**
* @var string The method to use for the link
*/
protected $method;
/**
* @var string The URI of the page where the link is embedded (or the base href)
*/
protected $currentUri;
/**
* Constructor.
*
* @param \DOMNode $node A \DOMNode instance
* @param string $currentUri The URI of the page where the link is embedded (or the base href)
* @param string $method The method to use for the link (get by default)
*
* @throws \InvalidArgumentException if the node is not a link
*
* @api
*/
public function __construct(\DOMNode $node, $currentUri, $method = 'GET')
{
if (!in_array(substr($currentUri, 0, 4), array('http', 'file'))) {
throw new \InvalidArgumentException(sprintf('Current URI must be an absolute URL ("%s").', $currentUri));
}
$this->setNode($node);
$this->method = $method ? strtoupper($method) : null;
$this->currentUri = $currentUri;
}
/**
* Gets the node associated with this link.
*
* @return \DOMNode A \DOMNode instance
*/
public function getNode()
{
return $this->node;
}
/**
* Gets the method associated with this link.
*
* @return string The method
*
* @api
*/
public function getMethod()
{
return $this->method;
}
/**
* Gets the URI associated with this link.
*
* @return string The URI
*
* @api
*/
public function getUri()
{
$uri = trim($this->getRawUri());
// absolute URL?
if (0 === strpos($uri, 'http')) {
return $uri;
}
// empty URI
if (!$uri) {
return $this->currentUri;
}
// only an anchor
if ('#' === $uri[0]) {
$baseUri = $this->currentUri;
if (false !== $pos = strpos($baseUri, '#')) {
$baseUri = substr($baseUri, 0, $pos);
}
return $baseUri.$uri;
}
// only a query string
if ('?' === $uri[0]) {
$baseUri = $this->currentUri;
// remove the query string from the current uri
if (false !== $pos = strpos($baseUri, '?')) {
$baseUri = substr($baseUri, 0, $pos);
}
return $baseUri.$uri;
}
// absolute path
if ('/' === $uri[0]) {
return preg_replace('#^(.*?//[^/]+)(?:\/.*)?$#', '$1', $this->currentUri).$uri;
}
// relative path
return substr($this->currentUri, 0, strrpos($this->currentUri, '/') + 1).$uri;
}
/**
* Returns raw uri data
*
* @return string
*/
protected function getRawUri()
{
return $this->node->getAttribute('href');
}
/**
* Sets current \DOMNode instance
*
* @param \DOMNode $node A \DOMNode instance
*
* @throws \LogicException If given node is not an anchor
*/
protected function setNode(\DOMNode $node)
{
if ('a' != $node->nodeName) {
throw new \LogicException(sprintf('Unable to click on a "%s" tag.', $node->nodeName));
}
$this->node = $node;
}
}

View File

@@ -1,23 +0,0 @@
<?php
/* Configure session cache */
session_cache_limiter('nocache');
session_start();
include_once "gda-utils.php";
include_once "gda-config.php";
header('Content-type: text/plain; charset=UTF-8');
$cmdfile = get_command_filename (session_id ());
$replyfile = get_reply_filename (session_id ());
@unlink ($cmdfile);
@unlink ($replyfile);
/* all cleaned */
$reply = new SimpleXMLElement("<reply></reply>");
$reply->addChild ("status", "OK");
echo gda_add_hash ($init_shared, $reply->asXml());
session_destroy ();
?>

View File

@@ -1,238 +0,0 @@
#!/usr/bin/env python
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is standalone Firefox Windows performance test.
#
# The Initial Developer of the Original Code is Google Inc.
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Alice Nodelman <anodelman@mozilla.com> (original author)
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
__author__ = 'anodelman@mozilla.com (Alice Nodelman)'
import os
import time
import subprocess
import threading
import platform
from ffprocess_linux import LinuxProcess
from ffprocess_mac import MacProcess
from ffprocess_win32 import Win32Process
from utils import talosError
import sys
import getopt
import stat
if platform.system() == "Linux":
platform_type = 'linux_'
ffprocess = LinuxProcess()
elif platform.system() in ("Windows", "Microsoft"):
import win32pdh
import win32api
import win32event
import win32con
platform_type = 'win_'
ffprocess = Win32Process()
elif platform.system() == "Darwin":
platform_type = 'mac_'
ffprocess = MacProcess()
class BrowserWaiter(threading.Thread):
def __init__(self, command, log, mod, deviceManager = None):
self.command = command
self.log = log
self.mod = mod
self.endTime = -1
self.returncode = -1
self.deviceManager = deviceManager
threading.Thread.__init__(self)
self.start()
def run(self):
if self.mod:
if (self.deviceManager.__class__.__name__ == "WinmoProcess"):
if (self.mod == "str(int(time.time()*1000))"):
self.command += self.deviceManager.getCurrentTime()
else:
self.command = self.command + eval(self.mod)
if (self.deviceManager.__class__.__name__ == "WinmoProcess"):
retVal = self.deviceManager.launchProcess(self.command, timeout=600)
if retVal <> None:
self.deviceManager.getFile(retVal, self.log)
self.returncode = 0
else:
self.returncode = 1
else: #blocking call to system
self.returncode = os.system(self.command + " > " + self.log)
self.endTime = int(time.time()*1000)
def hasTime(self):
return self.endTime > -1
def getTime(self):
return self.endTime
def getReturn(self):
def innerMethod(self):
pass
return self.returncode
def testMethod2(self):
class InnerClass:
def innerInnerMethod(self):
pass
return
class Test:
def testMethod(self):
pass
class BrowserController:
def __init__(self, command, mod, name, child_process,
timeout, log, host='', port=20701, root=''):
global ffprocess
self.command = command
self.mod = mod
self.process_name = name
self.child_process = child_process
self.browser_wait = timeout
self.log = log
self.timeout = 1200 #no output from the browser in 20 minutes = failure
self.host = host
self.port = port
self.root = root
if (host <> ''):
from ffprocess_winmo import WinmoProcess
platform_type = 'win_'
ffprocess = WinmoProcess(host, port, root)
self.ffprocess = ffprocess
def run(self):
self.bwaiter = BrowserWaiter(self.command, self.log, self.mod, self.ffprocess)
noise = 0
prev_size = 0
while not self.bwaiter.hasTime():
if noise > self.timeout: # check for frozen browser
try:
ffprocess.cleanupProcesses(self.process_name, self.child_process, self.browser_wait)
except talosError, te:
os.abort() #kill myself off because something horrible has happened
os.chmod(self.log, 0777)
results_file = open(self.log, "a")
results_file.write("\n__FAILbrowser frozen__FAIL\n")
results_file.close()
return
time.sleep(1)
try:
open(self.log, "r").close() #HACK FOR WINDOWS: refresh the file information
size = os.path.getsize(self.log)
except:
size = 0
if size > prev_size:
prev_size = size
noise = 0
else:
noise += 1
results_file = open(self.log, "a")
if self.bwaiter.getReturn() != 0: #the browser shutdown, but not cleanly
results_file.write("\n__FAILbrowser non-zero return code (%d)__FAIL\n" % self.bwaiter.getReturn())
return
results_file.write("__startSecondTimestamp%d__endSecondTimestamp\n" % self.bwaiter.getTime())
results_file.close()
return
def main(argv=None):
command = ""
name = "firefox" #default
child_process = "plugin-container" #default
timeout = ""
log = ""
mod = ""
host = ""
deviceRoot = ""
port = 20701
if argv is None:
argv = sys.argv
opts, args = getopt.getopt(argv[1:], "c:t:n:p:l:m:h:r:o", ["command=", "timeout=", "name=", "child_process=", "log=", "mod=", "host=", "deviceRoot=", "port="])
# option processing
for option, value in opts:
if option in ("-c", "--command"):
command = value
if option in ("-t", "--timeout"):
timeout = int(value)
if option in ("-n", "--name"):
name = value
if option in ("-p", "--child_process"):
child_process = value
if option in ("-l", "--log"):
log = value
if option in ("-m", "--mod"):
mod = value
if option in ("-h", "--host"):
host = value
if option in ("-r", "--deviceRoot"):
deviceRoot = value
if option in ("-o", "--port"):
port = value
if command and timeout and log:
bcontroller = BrowserController(command, mod, name, child_process, timeout, log, host, port, deviceRoot)
bcontroller.run()
else:
print "\nFAIL: no command\n"
sys.stdout.flush()
class mainClass:
def mainClassMethod(self):
pass
pass
def mainMethod(self):
class mainMethodClass:
pass
pass
if __name__ == "__main__":
sys.exit(main())

View File

@@ -1,697 +0,0 @@
"""
Makefile functions.
"""
import parser, util
import subprocess, os, logging
from globrelative import glob
from cStringIO import StringIO
log = logging.getLogger('pymake.data')
class Function(object):
"""
An object that represents a function call. This class is always subclassed
with the following methods and attributes:
minargs = minimum # of arguments
maxargs = maximum # of arguments (0 means unlimited)
def resolve(self, makefile, variables, fd, setting)
Calls the function
calls fd.write() with strings
"""
__slots__ = ('_arguments', 'loc')
def __init__(self, loc):
self._arguments = []
self.loc = loc
assert self.minargs > 0
def __getitem__(self, key):
return self._arguments[key]
def setup(self):
argc = len(self._arguments)
if argc < self.minargs:
raise data.DataError("Not enough arguments to function %s, requires %s" % (self.name, self.minargs), self.loc)
assert self.maxargs == 0 or argc <= self.maxargs, "Parser screwed up, gave us too many args"
def append(self, arg):
assert isinstance(arg, (data.Expansion, data.StringExpansion))
self._arguments.append(arg)
def __len__(self):
return len(self._arguments)
class VariableRef(Function):
__slots__ = ('vname', 'loc')
def __init__(self, loc, vname):
self.loc = loc
assert isinstance(vname, (data.Expansion, data.StringExpansion))
self.vname = vname
def setup(self):
assert False, "Shouldn't get here"
def resolve(self, makefile, variables, fd, setting):
vname = self.vname.resolvestr(makefile, variables, setting)
if vname in setting:
raise data.DataError("Setting variable '%s' recursively references itself." % (vname,), self.loc)
flavor, source, value = variables.get(vname)
if value is None:
log.debug("%s: variable '%s' was not set" % (self.loc, vname))
return
value.resolve(makefile, variables, fd, setting + [vname])
class SubstitutionRef(Function):
"""$(VARNAME:.c=.o) and $(VARNAME:%.c=%.o)"""
__slots__ = ('loc', 'vname', 'substfrom', 'substto')
def __init__(self, loc, varname, substfrom, substto):
self.loc = loc
self.vname = varname
self.substfrom = substfrom
self.substto = substto
def setup(self):
assert False, "Shouldn't get here"
def resolve(self, makefile, variables, fd, setting):
vname = self.vname.resolvestr(makefile, variables, setting)
if vname in setting:
raise data.DataError("Setting variable '%s' recursively references itself." % (vname,), self.loc)
substfrom = self.substfrom.resolvestr(makefile, variables, setting)
substto = self.substto.resolvestr(makefile, variables, setting)
flavor, source, value = variables.get(vname)
if value is None:
log.debug("%s: variable '%s' was not set" % (self.loc, vname))
return
f = data.Pattern(substfrom)
if not f.ispattern():
f = data.Pattern('%' + substfrom)
substto = '%' + substto
fd.write(' '.join([f.subst(substto, word, False)
for word in value.resolvesplit(makefile, variables, setting + [vname])]))
class SubstFunction(Function):
name = 'subst'
minargs = 3
maxargs = 3
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
s = self._arguments[0].resolvestr(makefile, variables, setting)
r = self._arguments[1].resolvestr(makefile, variables, setting)
d = self._arguments[2].resolvestr(makefile, variables, setting)
fd.write(d.replace(s, r))
class PatSubstFunction(Function):
name = 'patsubst'
minargs = 3
maxargs = 3
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
s = self._arguments[0].resolvestr(makefile, variables, setting)
r = self._arguments[1].resolvestr(makefile, variables, setting)
p = data.Pattern(s)
fd.write(' '.join([p.subst(r, word, False)
for word in self._arguments[2].resolvesplit(makefile, variables, setting)]))
class StripFunction(Function):
name = 'strip'
minargs = 1
maxargs = 1
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
util.joiniter(fd, self._arguments[0].resolvesplit(makefile, variables, setting))
class FindstringFunction(Function):
name = 'findstring'
minargs = 2
maxargs = 2
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
s = self._arguments[0].resolvestr(makefile, variables, setting)
r = self._arguments[1].resolvestr(makefile, variables, setting)
if r.find(s) == -1:
return
fd.write(s)
class FilterFunction(Function):
name = 'filter'
minargs = 2
maxargs = 2
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
plist = [data.Pattern(p)
for p in self._arguments[0].resolvesplit(makefile, variables, setting)]
fd.write(' '.join([w for w in self._arguments[1].resolvesplit(makefile, variables, setting)
if util.any((p.match(w) for p in plist))]))
class FilteroutFunction(Function):
name = 'filter-out'
minargs = 2
maxargs = 2
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
plist = [data.Pattern(p)
for p in self._arguments[0].resolvesplit(makefile, variables, setting)]
fd.write(' '.join([w for w in self._arguments[1].resolvesplit(makefile, variables, setting)
if not util.any((p.match(w) for p in plist))]))
class SortFunction(Function):
name = 'sort'
minargs = 1
maxargs = 1
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
d = list(self._arguments[0].resolvesplit(makefile, variables, setting))
d.sort()
util.joiniter(fd, d)
class WordFunction(Function):
name = 'word'
minargs = 2
maxargs = 2
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
n = self._arguments[0].resolvestr(makefile, variables, setting)
# TODO: provide better error if this doesn't convert
n = int(n)
words = list(self._arguments[1].resolvesplit(makefile, variables, setting))
if n < 1 or n > len(words):
return
fd.write(words[n - 1])
class WordlistFunction(Function):
name = 'wordlist'
minargs = 3
maxargs = 3
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
nfrom = self._arguments[0].resolvestr(makefile, variables, setting)
nto = self._arguments[1].resolvestr(makefile, variables, setting)
# TODO: provide better errors if this doesn't convert
nfrom = int(nfrom)
nto = int(nto)
words = list(self._arguments[2].resolvesplit(makefile, variables, setting))
if nfrom < 1:
nfrom = 1
if nto < 1:
nto = 1
util.joiniter(fd, words[nfrom - 1:nto])
class WordsFunction(Function):
name = 'words'
minargs = 1
maxargs = 1
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
fd.write(str(len(self._arguments[0].resolvesplit(makefile, variables, setting))))
class FirstWordFunction(Function):
name = 'firstword'
minargs = 1
maxargs = 1
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
l = self._arguments[0].resolvesplit(makefile, variables, setting)
if len(l):
fd.write(l[0])
class LastWordFunction(Function):
name = 'lastword'
minargs = 1
maxargs = 1
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
l = self._arguments[0].resolvesplit(makefile, variables, setting)
if len(l):
fd.write(l[-1])
def pathsplit(path, default='./'):
"""
Splits a path into dirpart, filepart on the last slash. If there is no slash, dirpart
is ./
"""
dir, slash, file = util.strrpartition(path, '/')
if dir == '':
return default, file
return dir + slash, file
class DirFunction(Function):
name = 'dir'
minargs = 1
maxargs = 1
def resolve(self, makefile, variables, fd, setting):
fd.write(' '.join([pathsplit(path)[0]
for path in self._arguments[0].resolvesplit(makefile, variables, setting)]))
class NotDirFunction(Function):
name = 'notdir'
minargs = 1
maxargs = 1
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
fd.write(' '.join([pathsplit(path)[1]
for path in self._arguments[0].resolvesplit(makefile, variables, setting)]))
class SuffixFunction(Function):
name = 'suffix'
minargs = 1
maxargs = 1
__slots__ = Function.__slots__
@staticmethod
def suffixes(words):
for w in words:
dir, file = pathsplit(w)
base, dot, suffix = util.strrpartition(file, '.')
if base != '':
yield dot + suffix
def resolve(self, makefile, variables, fd, setting):
util.joiniter(fd, self.suffixes(self._arguments[0].resolvesplit(makefile, variables, setting)))
class BasenameFunction(Function):
name = 'basename'
minargs = 1
maxargs = 1
__slots__ = Function.__slots__
@staticmethod
def basenames(words):
for w in words:
dir, file = pathsplit(w, '')
base, dot, suffix = util.strrpartition(file, '.')
if dot == '':
base = suffix
yield dir + base
def resolve(self, makefile, variables, fd, setting):
util.joiniter(fd, self.basenames(self._arguments[0].resolvesplit(makefile, variables, setting)))
class AddSuffixFunction(Function):
name = 'addprefix'
minargs = 2
maxargs = 2
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
suffix = self._arguments[0].resolvestr(makefile, variables, setting)
fd.write(' '.join([w + suffix for w in self._arguments[1].resolvesplit(makefile, variables, setting)]))
class AddPrefixFunction(Function):
name = 'addsuffix'
minargs = 2
maxargs = 2
def resolve(self, makefile, variables, fd, setting):
prefix = self._arguments[0].resolvestr(makefile, variables, setting)
fd.write(' '.join([prefix + w for w in self._arguments[1].resolvesplit(makefile, variables, setting)]))
class JoinFunction(Function):
name = 'join'
minargs = 2
maxargs = 2
__slots__ = Function.__slots__
@staticmethod
def iterjoin(l1, l2):
for i in xrange(0, max(len(l1), len(l2))):
i1 = i < len(l1) and l1[i] or ''
i2 = i < len(l2) and l2[i] or ''
yield i1 + i2
def resolve(self, makefile, variables, fd, setting):
list1 = list(self._arguments[0].resolvesplit(makefile, variables, setting))
list2 = list(self._arguments[1].resolvesplit(makefile, variables, setting))
util.joiniter(fd, self.iterjoin(list1, list2))
class WildcardFunction(Function):
name = 'wildcard'
minargs = 1
maxargs = 1
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
patterns = self._arguments[0].resolvesplit(makefile, variables, setting)
fd.write(' '.join([x.replace('\\','/')
for p in patterns
for x in glob(makefile.workdir, p)]))
__slots__ = Function.__slots__
class RealpathFunction(Function):
name = 'realpath'
minargs = 1
maxargs = 1
def resolve(self, makefile, variables, fd, setting):
fd.write(' '.join([os.path.realpath(os.path.join(makefile.workdir, path)).replace('\\', '/')
for path in self._arguments[0].resolvesplit(makefile, variables, setting)]))
class AbspathFunction(Function):
name = 'abspath'
minargs = 1
maxargs = 1
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
assert os.path.isabs(makefile.workdir)
fd.write(' '.join([util.normaljoin(makefile.workdir, path).replace('\\', '/')
for path in self._arguments[0].resolvesplit(makefile, variables, setting)]))
class IfFunction(Function):
name = 'if'
minargs = 1
maxargs = 3
__slots__ = Function.__slots__
def setup(self):
Function.setup(self)
self._arguments[0].lstrip()
self._arguments[0].rstrip()
def resolve(self, makefile, variables, fd, setting):
condition = self._arguments[0].resolvestr(makefile, variables, setting)
if len(condition):
self._arguments[1].resolve(makefile, variables, fd, setting)
elif len(self._arguments) > 2:
return self._arguments[2].resolve(makefile, variables, fd, setting)
class OrFunction(Function):
name = 'or'
minargs = 1
maxargs = 0
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
for arg in self._arguments:
r = arg.resolvestr(makefile, variables, setting)
if r != '':
fd.write(r)
return
class AndFunction(Function):
name = 'and'
minargs = 1
maxargs = 0
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
r = ''
for arg in self._arguments:
r = arg.resolvestr(makefile, variables, setting)
if r == '':
return
fd.write(r)
class ForEachFunction(Function):
name = 'foreach'
minargs = 3
maxargs = 3
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
vname = self._arguments[0].resolvestr(makefile, variables, setting)
e = self._arguments[2]
v = data.Variables(parent=variables)
firstword = True
for w in self._arguments[1].resolvesplit(makefile, variables, setting):
if firstword:
firstword = False
else:
fd.write(' ')
v.set(vname, data.Variables.FLAVOR_SIMPLE, data.Variables.SOURCE_AUTOMATIC, w)
e.resolve(makefile, v, fd, setting)
class CallFunction(Function):
name = 'call'
minargs = 1
maxargs = 0
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
vname = self._arguments[0].resolvestr(makefile, variables, setting)
if vname in setting:
raise data.DataError("Recursively setting variable '%s'" % (vname,))
v = data.Variables(parent=variables)
v.set('0', data.Variables.FLAVOR_SIMPLE, data.Variables.SOURCE_AUTOMATIC, vname)
for i in xrange(1, len(self._arguments)):
param = self._arguments[i].resolvestr(makefile, variables, setting)
v.set(str(i), data.Variables.FLAVOR_SIMPLE, data.Variables.SOURCE_AUTOMATIC, param)
flavor, source, e = variables.get(vname)
if e is None:
return
if flavor == data.Variables.FLAVOR_SIMPLE:
log.warning("%s: calling variable '%s' which is simply-expanded" % (self.loc, vname))
# but we'll do it anyway
e.resolve(makefile, v, fd, setting + [vname])
class ValueFunction(Function):
name = 'value'
minargs = 1
maxargs = 1
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
varname = self._arguments[0].resolvestr(makefile, variables, setting)
flavor, source, value = variables.get(varname, expand=False)
if value is not None:
fd.write(value)
class EvalFunction(Function):
name = 'eval'
minargs = 1
maxargs = 1
def resolve(self, makefile, variables, fd, setting):
if makefile.parsingfinished:
# GNU make allows variables to be set by recursive expansion during
# command execution. This seems really dumb to me, so I don't!
raise data.DataError("$(eval) not allowed via recursive expansion after parsing is finished", self.loc)
stmts = parser.parsestring(self._arguments[0].resolvestr(makefile, variables, setting),
'evaluation from %s' % self.loc)
stmts.execute(makefile)
class OriginFunction(Function):
name = 'origin'
minargs = 1
maxargs = 1
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
vname = self._arguments[0].resolvestr(makefile, variables, setting)
flavor, source, value = variables.get(vname)
if source is None:
r = 'undefined'
elif source == data.Variables.SOURCE_OVERRIDE:
r = 'override'
elif source == data.Variables.SOURCE_MAKEFILE:
r = 'file'
elif source == data.Variables.SOURCE_ENVIRONMENT:
r = 'environment'
elif source == data.Variables.SOURCE_COMMANDLINE:
r = 'command line'
elif source == data.Variables.SOURCE_AUTOMATIC:
r = 'automatic'
elif source == data.Variables.SOURCE_IMPLICIT:
r = 'default'
fd.write(r)
class FlavorFunction(Function):
name = 'flavor'
minargs = 1
maxargs = 1
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
varname = self._arguments[0].resolvestr(makefile, variables, setting)
flavor, source, value = variables.get(varname)
if flavor is None:
r = 'undefined'
elif flavor == data.Variables.FLAVOR_RECURSIVE:
r = 'recursive'
elif flavor == data.Variables.FLAVOR_SIMPLE:
r = 'simple'
fd.write(r)
class ShellFunction(Function):
name = 'shell'
minargs = 1
maxargs = 1
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
#TODO: call this once up-front somewhere and save the result?
shell, msys = util.checkmsyscompat()
cline = self._arguments[0].resolvestr(makefile, variables, setting)
log.debug("%s: running shell command '%s'" % (self.loc, cline))
if msys:
cline = [shell, "-c", cline]
p = subprocess.Popen(cline, shell=not msys, stdout=subprocess.PIPE, cwd=makefile.workdir)
stdout, stderr = p.communicate()
stdout = stdout.replace('\r\n', '\n')
if stdout.endswith('\n'):
stdout = stdout[:-1]
stdout = stdout.replace('\n', ' ')
fd.write(stdout)
class ErrorFunction(Function):
name = 'error'
minargs = 1
maxargs = 1
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
v = self._arguments[0].resolvestr(makefile, variables, setting)
raise data.DataError(v, self.loc)
class WarningFunction(Function):
name = 'warning'
minargs = 1
maxargs = 1
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
v = self._arguments[0].resolvestr(makefile, variables, setting)
log.warning(v)
class InfoFunction(Function):
name = 'info'
minargs = 1
maxargs = 1
__slots__ = Function.__slots__
def resolve(self, makefile, variables, fd, setting):
v = self._arguments[0].resolvestr(makefile, variables, setting)
print v
functionmap = {
'subst': SubstFunction,
'patsubst': PatSubstFunction,
'strip': StripFunction,
'findstring': FindstringFunction,
'filter': FilterFunction,
'filter-out': FilteroutFunction,
'sort': SortFunction,
'word': WordFunction,
'wordlist': WordlistFunction,
'words': WordsFunction,
'firstword': FirstWordFunction,
'lastword': LastWordFunction,
'dir': DirFunction,
'notdir': NotDirFunction,
'suffix': SuffixFunction,
'basename': BasenameFunction,
'addsuffix': AddSuffixFunction,
'addprefix': AddPrefixFunction,
'join': JoinFunction,
'wildcard': WildcardFunction,
'realpath': RealpathFunction,
'abspath': AbspathFunction,
'if': IfFunction,
'or': OrFunction,
'and': AndFunction,
'foreach': ForEachFunction,
'call': CallFunction,
'value': ValueFunction,
'eval': EvalFunction,
'origin': OriginFunction,
'flavor': FlavorFunction,
'shell': ShellFunction,
'error': ErrorFunction,
'warning': WarningFunction,
'info': InfoFunction,
}
import data

View File

@@ -1,13 +0,0 @@
#!/usr/bin/env python
class ClassName(object):
"""docstring for ClassName"""
def __init__(self, arg):
super(ClassName, self).__init__()
self.arg = arg
def function1(self):
foo = """
foostring
"""
def function2(self):
pass

View File

@@ -1,50 +0,0 @@
from django.db import models
from django.contrib.auth.models import User
from django.contrib import admin
from string import join
from settings import MEDIA_ROOT
class Forum(models.Model):
title = models.CharField(max_length=60)
def __unicode__(self):
return self.title
class Thread(models.Model):
title = models.CharField(max_length=60)
created = models.DateTimeField(auto_now_add=True)
creator = models.ForeignKey(User, blank=True, null=True)
forum = models.ForeignKey(Forum)
def __unicode__(self):
return unicode(self.creator) + " - " + self.title
class Post(models.Model):
title = models.CharField(max_length=60)
created = models.DateTimeField(auto_now_add=True)
creator = models.ForeignKey(User, blank=True, null=True)
thread = models.ForeignKey(Thread)
body = models.TextField(max_length=10000)
def __unicode__(self):
return u"%s - %s - %s" % (self.creator, self.thread, self.title)
def short(self):
return u"%s - %s\n%s" % (self.creator, self.title, self.created.strftime("%b %d, %I:%M %p"))
short.allow_tags = True
### Admin
class ForumAdmin(admin.ModelAdmin):
pass
class ThreadAdmin(admin.ModelAdmin):
list_display = ["title", "forum", "creator", "created"]
list_filter = ["forum", "creator"]
class PostAdmin(admin.ModelAdmin):
search_fields = ["title", "creator"]
list_display = ["title", "thread", "creator", "created"]
admin.site.register(Forum, ForumAdmin)
admin.site.register(Thread, ThreadAdmin)
admin.site.register(Post, PostAdmin)

View File

@@ -1,3 +0,0 @@
def foo(a, b, \
c, d):
pass

View File

@@ -1,3 +0,0 @@
def find_heading(self, position=0, direction=Direction.FORWARD, \
heading=Heading, connect_with_document=True):
pass

View File

@@ -1,23 +0,0 @@
import foo
import bar
defaultdict(lambda: 0)
classofhello = 0
class test(foo, bar):
class Inner:
# pass
def foo(self):
print "Inner"
# pass
def test():
class Inner2:
def bar(self):
print "Inner2"
# t = Inner2()
# pass
#print "Test"
#r = test.Inner2()
#test()

View File

@@ -1,3 +0,0 @@
from test import *
r = test.Inner()

View File

@@ -1,225 +0,0 @@
#!/usr/bin/env python2.6
from __future__ import division
import gtk
import numpy as np
import matplotlib
matplotlib.use('GTKAgg')
import matplotlib.cm as cm
import matplotlib.pyplot as plt
from matplotlib.widgets import Button, RadioButtons
from matplotlib.backends.backend_gtkagg import FigureCanvasGTKAgg as FigureCanvas
win = gtk.Window()
win.connect("destroy", gtk.main_quit)
win.set_default_size(600,600)
win.set_title("Resource Visualisation")
fig = plt.figure(figsize=(8,8))
ax = fig.add_axes([0.1, 0.2, 0.8, 0.75], projection='polar')
rax = fig.add_axes([0.7, 0.05, 0.2, 0.05])
rax.grid(False)
rax.set_xticks([])
rax.set_yticks([])
moax = fig.add_axes([0.1, 0.02, 0.25, 0.1])
moax.grid(False)
moax.set_xticks([])
moax.set_yticks([])
logax = fig.add_axes([0.4, 0.02, 0.25, 0.1])
logax.grid(False)
logax.set_xticks([])
logax.set_yticks([])
canvas = FigureCanvas(fig)
win.add(canvas)
class ResVis(object):
def __init__(self):
self.dirdata = self.load_data('dirs.dat')
self.userdata = self.load_data('users.dat')
self.mode = 'dir'
self.log = True
self.draw_dir('root')
def load_data(self, filename):
data = {}
for line in open(filename, 'r').readlines():
entry = line.split(None, 3)
if len(entry) > 3: # current entry has subentries
entry[3] = entry[3].split()
entry[3].sort(key=str.lower)
else:
entry.append([])
data[entry[0]] = [entry[0], float(entry[1]), float(entry[2]),
entry[3]]
return data
def load_dir(self, dirname):
curdirdata = []
for d in self.dirdata[dirname][3]:
curdirdata.append(self.dirdata[d])
return curdirdata
def load_user(self, username):
curdata = []
for u in self.userdata[username][3]:
curdata.append(self.userdata[u])
return curdata
def draw_dir(self, dirname='root'):
self.curdir = dirname
self.reset_ax()
ax.set_title('Directory size')
ax.set_xlabel(dirname, weight='bold')
curdir = self.load_dir(dirname)
self.draw_data(curdir)
def draw_user(self, username='root'):
self.curuser = username
self.reset_ax()
ax.set_title('Resource usage')
ax.set_xlabel(username, weight='bold')
user = self.load_user(username)
self.draw_data(user)
def reset_ax(self):
ax.cla()
#ax.axis('off')
#ax.set_axis_off()
#ax.set_yscale('log')
ax.grid(False)
ax.set_xticks([]) # edge
ax.set_yticks([]) # radius
#ax.set_xlabel('Size')
#ax.set_ylabel('Number of files')
def draw_data(self, data):
totalsize = sum(zip(*data)[1]) # get sum of subentry sizes
unit = 1.5 * np.pi / totalsize
angle = 0.5 * np.pi
if self.log:
maxy = max(map(np.log2, zip(*data)[2]))
else:
maxy = max(zip(*data)[2])
for d in data:
relangle = unit * d[1]
if len(d[3]) > 0 or self.mode == 'user':
# scale colours since the legend occupies a quarter
scaledangle = (angle - 0.5*np.pi) * (2 / 1.5)
colour = cm.hsv(scaledangle/(2*np.pi))
else:
# colour = cm.Greys(scaledangle/(2*np.pi))
colour = "#999999"
if self.log:
# take logarithm to accomodate for big differences
y = np.log2(d[2])
else:
y = d[2]
bar = ax.bar(angle, y, width=relangle, bottom=maxy*0.2,
color=colour, label=d[0],
picker=True)
angle += relangle
if self.mode == 'dir':
desc = '{0}\n{1}G'.format(d[0], d[1])
elif self.mode == 'user':
desc = '{0}\n{1}%'.format(d[0], d[1])
self.draw_desc(bar[0], d, desc)
self.draw_legend(maxy)
fig.canvas.draw()
def draw_desc(self, bar, data, text):
# show description in center of bar
bbox = bar.get_bbox()
x = bbox.xmin + (bbox.xmax - bbox.xmin) / 2
y = bbox.ymin + (bbox.ymax - bbox.ymin) / 2
ax.text(x, y, text, horizontalalignment='center',
verticalalignment='center', weight='bold')
def draw_legend(self, maxy):
ax.annotate('', xy=(0, maxy*0.3), xytext=(0.5*np.pi, maxy*0.3),
arrowprops=dict(
arrowstyle='<->',
connectionstyle='angle3,angleA=0,angleB=-90',
linewidth=3))
ax.annotate('', xy=(0.04*np.pi, maxy*0.35), xytext=(0.04*np.pi, maxy),
arrowprops=dict(
arrowstyle='<->',
connectionstyle='arc3',
linewidth=3))
if self.mode == 'dir':
xtext = 'Size'
ytext = 'Number of files'
elif self.mode == 'user':
xtext = 'Processor usage'
ytext = 'Memory usage'
ax.text(0.3*np.pi, maxy*0.35, xtext, weight='normal')
ax.text(0.06*np.pi, maxy*0.4, ytext, weight='normal', rotation=8)
if self.mode == 'dir':
ax.text(0.3*np.pi, maxy*0.6, 'Grey dirs do not\nhave subdirs.')
def on_pick(self, event):
clicked = event.artist.get_label()
if self.mode == 'dir' and len(self.dirdata[clicked][3]) > 0:
self.draw_dir(clicked)
elif self.mode == 'user' and len(self.userdata[clicked][3]) > 0:
self.draw_user(clicked)
def on_rootclick(self, event):
if self.mode == 'dir':
self.draw_dir('root')
elif self.mode == 'user':
self.draw_user('root')
def on_modeclick(self, mode):
if mode == 'Directory size':
self.mode = 'dir'
self.draw_dir('root')
elif mode == 'Resource usage':
self.mode = 'user'
self.draw_user('root')
def on_logclick(self, mode):
self.log = mode == 'Logarithmic'
if self.mode == 'dir':
self.draw_dir(self.curdir)
if self.mode == 'user':
self.draw_user(self.curuser)
vis = ResVis()
root = Button(rax, 'Home')
root.on_clicked(vis.on_rootclick)
mode = RadioButtons(moax, ('Directory size', 'Resource usage'))
mode.on_clicked(vis.on_modeclick)
log = RadioButtons(logax, ('Logarithmic', 'Linear'))
log.on_clicked(vis.on_logclick)
fig.canvas.mpl_connect('pick_event', vis.on_pick)
#plt.show()
win.show_all()
gtk.main()

View File

@@ -1,10 +0,0 @@
class Class2
def self.fun1()
value=if foo
bar
end
end
def self.fun2()
end
end

Some files were not shown because too many files have changed in this diff Show More